Browse Source

Added a search feature in the Proximo articles + fixed typos in translations

Yohan Simard 2 years ago
parent
commit
9f4018a0de

+ 92
- 0
components/SearchHeader.js View File

@@ -0,0 +1,92 @@
1
+// @flow
2
+
3
+import * as React from "react";
4
+import {Header} from "native-base";
5
+import {Platform, StyleSheet} from "react-native";
6
+import {getStatusBarHeight} from "react-native-status-bar-height";
7
+import Touchable from 'react-native-platform-touchable';
8
+import ThemeManager from "../utils/ThemeManager";
9
+import CustomMaterialIcon from "./CustomMaterialIcon";
10
+import {TextInput} from "react-native-paper";
11
+import i18n from "i18n-js";
12
+
13
+
14
+type Props = {
15
+    navigation: Object,
16
+    searchFunction: Function
17
+};
18
+
19
+type State = {
20
+    searchString: string
21
+}
22
+
23
+
24
+/**
25
+ * Custom component defining a search header using native base
26
+ */
27
+export default class SearchHeader extends React.Component<Props, State> {
28
+    state = {
29
+        searchString: "Test",
30
+    };
31
+
32
+    render() {
33
+        /* TODO:
34
+            - hard coded color (not theme-specific),
35
+            - bugs with placeHolder and underlineColorAndroid (do not work),
36
+            - subtle offset of the text to fix in the inputText
37
+            - not tested on iOS
38
+         */
39
+        return (
40
+            <Header style={styles.header}>
41
+                <Touchable
42
+                    style={{
43
+                        alignItems: "center",
44
+                        flexDirection: "row",
45
+                        padding: 7,
46
+                    }}
47
+                    onPress={() => this.props.navigation.goBack()}>
48
+                    <CustomMaterialIcon
49
+                        color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
50
+                        icon="arrow-left" />
51
+                </Touchable>
52
+
53
+                <TextInput
54
+                    style={{
55
+                        flex: 1,
56
+                        backgroundColor: "#CA535D",
57
+                        margin: 7,
58
+                    }}
59
+                    underlineColorAndroid={"transparent"}
60
+                    placeHolder={i18n.t("proximoScreen.search")}
61
+                    autoFocus={true}
62
+                    onChangeText={text => this.setState({searchString: text})}
63
+                    onSubmitEditing={text => {
64
+                        this.setState({searchString: text});
65
+                        this.props.searchFunction(this.state.searchString);
66
+                    }}
67
+                />
68
+
69
+                <Touchable
70
+                    style={{
71
+                        alignItems: "center",
72
+                        flexDirection: "row",
73
+                        padding: 7,
74
+                    }}
75
+                    onPress={() => this.props.searchFunction(this.state.searchString)}>
76
+                    <CustomMaterialIcon
77
+                        color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
78
+                        icon="magnify"/>
79
+                </Touchable>
80
+            </Header>
81
+        );
82
+    }
83
+};
84
+
85
+
86
+// Fix header in status bar on Android
87
+const styles = StyleSheet.create({
88
+    header: {
89
+        paddingTop: getStatusBarHeight(),
90
+        height: 54 + getStatusBarHeight(),
91
+    },
92
+});

+ 3
- 1
navigation/AppNavigator.js View File

@@ -5,6 +5,7 @@ import {createMaterialBottomTabNavigatorWithInitialRoute} from './MainTabNavigat
5 5
 import SettingsScreen from '../screens/SettingsScreen';
6 6
 import AboutScreen from '../screens/About/AboutScreen';
7 7
 import ProximoListScreen from '../screens/Proximo/ProximoListScreen';
8
+import ProximoSearchScreen from "../screens/Proximo/ProximoSearchScreen";
8 9
 import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
9 10
 import ProxiwashAboutScreen from '../screens/Proxiwash/ProxiwashAboutScreen';
10 11
 import ProximoAboutScreen from '../screens/Proximo/ProximoAboutScreen';
@@ -26,6 +27,7 @@ function createAppContainerWithInitialRoute(initialRoute: string) {
26 27
                 Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute),
27 28
                 // Drawer: MainDrawerNavigator,
28 29
                 ProximoListScreen: {screen: ProximoListScreen},
30
+                ProximoSearchScreen: {screen: ProximoSearchScreen},
29 31
                 SettingsScreen: {screen: SettingsScreen},
30 32
                 AboutScreen: {screen: AboutScreen},
31 33
                 AboutDependenciesScreen: {screen: AboutDependenciesScreen},
@@ -42,7 +44,7 @@ function createAppContainerWithInitialRoute(initialRoute: string) {
42 44
                 initialRouteName: "Main",
43 45
                 mode: 'card',
44 46
                 headerMode: "none",
45
-                transitionConfig: () => fromRight(),
47
+                // transitionConfig: () => fromRight(),
46 48
             })
47 49
     );
48 50
 }

+ 19
- 7
screens/Proximo/ProximoMainScreen.js View File

@@ -79,13 +79,25 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
79 79
 
80 80
     getRightButton() {
81 81
         return (
82
-            <Touchable
83
-                style={{padding: 6}}
84
-                onPress={() => this.props.navigation.navigate('ProximoAboutScreen')}>
85
-                <CustomMaterialIcon
86
-                    color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
87
-                    icon="information"/>
88
-            </Touchable>
82
+            <View
83
+                style={{
84
+                    flexDirection:'row'
85
+                }}>
86
+                <Touchable
87
+                    style={{padding: 6}}
88
+                    onPress={() => this.props.navigation.navigate('ProximoSearchScreen', {data: this.state.fetchedData})}>
89
+                    <CustomMaterialIcon
90
+                        color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
91
+                        icon="magnify" />
92
+                </Touchable>
93
+                <Touchable
94
+                    style={{padding: 6}}
95
+                    onPress={() => this.props.navigation.navigate('ProximoAboutScreen')}>
96
+                    <CustomMaterialIcon
97
+                        color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
98
+                        icon="information"/>
99
+                </Touchable>
100
+            </View>
89 101
         );
90 102
     }
91 103
 

+ 111
- 0
screens/Proximo/ProximoSearchScreen.js View File

@@ -0,0 +1,111 @@
1
+// @flow
2
+
3
+import * as React from 'react';
4
+import {Body, Container, Content, Left, ListItem, Right, Text, Thumbnail,} from 'native-base';
5
+import {FlatList} from "react-native";
6
+import i18n from "i18n-js";
7
+import ThemeManager from "../../utils/ThemeManager";
8
+import SearchHeader from "../../components/SearchHeader";
9
+
10
+type Props = {
11
+    navigation: Object,
12
+};
13
+
14
+type State = {
15
+    filteredData: Array<Object>,
16
+};
17
+
18
+/**
19
+ * Class defining proximo's article list of a certain category.
20
+ */
21
+export default class ProximoSearchScreen extends React.Component<Props, State> {
22
+    state = {
23
+        filteredData: this.props.navigation.getParam('data', {articles: [{name: "Error"}]}).articles,
24
+    };
25
+
26
+
27
+    /**
28
+     * get color depending on quantity available
29
+     *
30
+     * @param availableStock
31
+     * @return
32
+     */
33
+    getStockColor(availableStock: number) {
34
+        let color: string;
35
+        if (availableStock > 3)
36
+            color = ThemeManager.getCurrentThemeVariables().brandSuccess;
37
+        else if (availableStock > 0)
38
+            color = ThemeManager.getCurrentThemeVariables().brandWarning;
39
+        else
40
+            color = ThemeManager.getCurrentThemeVariables().brandDanger;
41
+        return color;
42
+    }
43
+
44
+
45
+    showItemDetails(item: Object) {
46
+        //TODO: implement onClick function (copy-paste from ProximoListScreen)
47
+    }
48
+
49
+    /**
50
+     * Returns only the articles whose name contains str. Case and accents insensitive.
51
+     * @param str
52
+     * @returns {[]}
53
+     */
54
+    filterData(str: string) {
55
+        let filteredData = [];
56
+        const testStr: String = str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
57
+        const articles: Object = this.props.navigation.getParam('data', {articles: [{name: "Error"}]}).articles;
58
+        for (const article: Object of articles) {
59
+            const name: String = String(article.name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, ""));
60
+            if (name.includes(testStr)) {
61
+                filteredData.push(article)
62
+            }
63
+        }
64
+        return filteredData;
65
+    }
66
+
67
+    search(str: string) {
68
+        this.setState({
69
+            filteredData: this.filterData(str)
70
+        })
71
+    }
72
+
73
+    render() {
74
+        return (
75
+            <Container>
76
+                <SearchHeader searchFunction={this.search.bind(this)} navigation={this.props.navigation}/>
77
+                <Content>
78
+                    <FlatList
79
+                        data={this.state.filteredData}
80
+                        keyExtractor={(item) => item.name + item.code}
81
+                        style={{minHeight: 300, width: '100%'}}
82
+                        renderItem={({item}) =>
83
+                            <ListItem
84
+                                thumbnail
85
+                                onPress={() => {this.showItemDetails(item);}} >
86
+                                <Left>
87
+                                    <Thumbnail square source={{uri: item.image}}/>
88
+                                </Left>
89
+                                <Body>
90
+                                    <Text style={{marginLeft: 20}}>
91
+                                        {item.name}
92
+                                    </Text>
93
+                                    <Text note style={{
94
+                                        marginLeft: 20,
95
+                                        color: this.getStockColor(parseInt(item.quantity))
96
+                                    }}>
97
+                                        {item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
98
+                                    </Text>
99
+                                </Body>
100
+                                <Right>
101
+                                    <Text style={{fontWeight: "bold"}}>
102
+                                        {item.price}€
103
+                                    </Text>
104
+                                </Right>
105
+                            </ListItem>}
106
+                    />
107
+                </Content>
108
+            </Container>
109
+        );
110
+    }
111
+}

+ 4
- 3
translations/en.json View File

@@ -25,7 +25,7 @@
25 25
     },
26 26
     "slide4": {
27 27
       "title": "Proximo",
28
-      "text": "Are you short on pasta? Or you maybe you feel a little peckish, then look up your INSA shop's stock in real time"
28
+      "text": "Are you short on pasta? Or maybe you feel a little peckish, then look up your INSA shop's stock in real time"
29 29
     },
30 30
     "slide5": {
31 31
       "title": "Planex",
@@ -129,7 +129,8 @@
129 129
     "description": "The Proximo is your small grocery store maintained by students directly on the campus. Open every day from 18h30 to 19h30, we welcome you when you are short on pastas or sodas ! Different products for different problems, everything at cost price. You can pay by Lydia or cash.",
130 130
     "openingHours": "Openning Hours",
131 131
     "paymentMethods": "Payment Methods",
132
-    "paymentMethodsDescription": "Cash or Lydia"
132
+    "paymentMethodsDescription": "Cash or Lydia",
133
+    "search": "Search"
133 134
   },
134 135
   "proxiwashScreen": {
135 136
     "dryer": "Dryer",
@@ -141,7 +142,7 @@
141 142
     "listUpdateFail": "Error while updating machines state",
142 143
     "error": "Could not update machines state. Pull down to retry.",
143 144
     "loading": "Loading...",
144
-    "description": "This is the washing service operated by Promologis for INSA's residences (We don't mind if you do not live on the campus and you do your laundry here). The room is right next to the R2, with 3 dryers and 9 washers, is open 7d/7 24h/24 ! Here you can check their availability ! You can bring your own detergent, use the one given on site or buy it at the Proximo (cheaper than the one given by the machines ). You can pay b credit card or cash.",
145
+    "description": "This is the washing service operated by Promologis for INSA's residences (We don't mind if you do not live on the campus and you do your laundry here). The room is right next to the R2, with 3 dryers and 9 washers, is open 7d/7 24h/24 ! Here you can check their availability ! You can bring your own detergent, use the one given on site or buy it at the Proximo (cheaper than the one given by the machines ). You can pay by credit card or cash.",
145 146
     "informationTab": "Information",
146 147
     "paymentTab": "Payment",
147 148
     "tariffs": "Tariffs",

+ 13
- 12
translations/fr.json View File

@@ -21,11 +21,11 @@
21 21
     },
22 22
     "slide3": {
23 23
       "title": "N'oubliez plus votre linge !",
24
-      "text": "CAMPUS vous informe de la disponibilité des machines et vous permet d'être notifiés lorsque la vôtre se termine bientôt !"
24
+      "text": "CAMPUS vous informe de la disponibilité des machines et vous permet d'être notifié lorsque la vôtre se termine bientôt !"
25 25
     },
26 26
     "slide4": {
27 27
       "title": "Proximo",
28
-      "text": "Il vous manque des pâtes ? Ou un petit creux au gouter, regardez les stocks de votre supérette insaienne en temps réel"
28
+      "text": "Il vous manque des pâtes ? Ou un petit creux au goûter, regardez les stocks de votre supérette insaienne en temps réel"
29 29
     },
30 30
     "slide5": {
31 31
       "title": "Planex",
@@ -75,7 +75,7 @@
75 75
     "dashboard": {
76 76
       "seeMore": "Cliquez pour plus d'infos",
77 77
       "todayEventsTitle": "Événements aujourd'hui",
78
-      "todayEventsSubtitleNA": "Pas d'événements",
78
+      "todayEventsSubtitleNA": "Pas d'événement",
79 79
       "todayEventsSubtitle": " événement aujourd'hui",
80 80
       "todayEventsSubtitlePlural": " événements aujourd'hui",
81 81
       "proximoTitle": "Proximo",
@@ -126,10 +126,11 @@
126 126
     "listUpdateFail": "Erreur lors de la mise à jour de la list d'articles",
127 127
     "loading": "Chargement...",
128 128
     "inStock": "en stock",
129
-    "description": "Le Proximo c’est ta petite épicerie étudiante tenu par les étudiants directement sur le campus. Ouvert tous les jours de 18h30 à 19h30, nous t’accueillons et te souvent quand tu n’as plus de pâtes ou de diluant ! Différents produits pour différentes galère, le tout à prix coûtant. Tu peux payer par Lydia ou par espèce.",
129
+    "description": "Le Proximo c’est ta petite épicerie étudiante tenue par les étudiants directement sur le campus. Ouverte tous les jours de 18h30 à 19h30, nous t’accueillons et te sauvons quand tu n’as plus de pâtes ou de diluant ! Différents produits pour différentes galères, le tout à prix coûtant. Tu peux payer par Lydia ou par espèce.",
130 130
     "openingHours": "Horaires d'ouverture",
131 131
     "paymentMethods" : "Moyens de Paiement",
132
-    "paymentMethodsDescription" : "Espèce ou Lydia"
132
+    "paymentMethodsDescription" : "Espèce ou Lydia",
133
+    "search": "Rechercher"
133 134
   },
134 135
   "proxiwashScreen": {
135 136
     "dryer": "Sèche-Linge",
@@ -137,9 +138,9 @@
137 138
     "washer": "Lave-Linge",
138 139
     "washers": "Lave-Linges",
139 140
     "min": "min",
140
-    "listUpdated": "Etat des machines mis à jour",
141
-    "listUpdateFail": "Erreur lors de la mise à jour del'état des machines",
142
-    "error": "Impossible de mettre a jour l'état des machines. Tirez vers le bas pour reessayer.",
141
+    "listUpdated": "État des machines mis à jour",
142
+    "listUpdateFail": "Erreur lors de la mise à jour de l'état des machines",
143
+    "error": "Impossible de mettre a jour l'état des machines. Tirez vers le bas pour réessayer.",
143 144
     "loading": "Chargement...",
144 145
     "description": "C'est le service de laverie proposé par promologis pour les résidences INSA (On t'en voudra pas si tu loges pas sur le campus et que tu fais ta machine ici). Le local situé au pied du R2 avec ses 3 sèche-linges et 9 machines est ouvert 7J/7 24h/24 ! Ici tu peux vérifier leur disponibilité ! Tu peux amener ta lessive, la prendre sur place ou encore mieux l'acheter au Proximo (moins chère qu'à la laverie directement). Tu peux payer par CB ou espèces.",
145 146
     "informationTab": "Informations",
@@ -152,7 +153,7 @@
152 153
     "washerProcedure": "Déposer le linge dans le tambour sans le tasser et en respectant les charges.\n\nFermer la porte de l'appareil.\n\nSélectionner un programme avec l'une des quatre touches de programme favori standard.\n\nAprès avoir payé à la centrale de commande, appuyer sur le bouton marqué START du lave-linge.\n\nDès que le programme est terminé, l’afficheur indique 'Programme terminé', appuyer sur le bouton jaune d’ouverture du hublot pour récupérer le linge.",
153 154
     "washerTips": "Programme blanc/couleur : 6kg de linge sec (textiles en coton, lin, linge de corps, draps, jeans,serviettes de toilettes).\n\nProgramme nonrepassable : 3,5 kg de linge sec (textiles en fibres synthétiques, cotonet polyester mélangés).\n\nProgramme fin 30°C : 2,5 kg de linge sec (textiles délicats en fibres synthétiques, rayonne).\n\nProgramme laine 30°C : 2,5 kg de linge sec (textiles en laine et lainages lavables).",
154 155
     "dryerProcedure": "Déposer le linge dans le tambour sans le tasser et en respectant les charges.\n\nFermer la porte de l'appareil.\n\nSélectionner un programme avec l'une des quatre touches de programme favori standard.\n\nAprès avoir payé à la centrale de commande, appuyer sur le bouton marqué START du lave-linge.",
155
-    "dryerTips": "La durée conseillée est de 35 minutes pour 14kg de linge. Vous pouvez choisir une durée plus courte si le seche-linge n'est pas chargé.",
156
+    "dryerTips": "La durée conseillée est de 35 minutes pour 14kg de linge. Vous pouvez choisir une durée plus courte si le sèche-linge n'est pas chargé.",
156 157
     "procedure": "Procédure",
157 158
     "tips": "Conseils",
158 159
 
@@ -161,7 +162,7 @@
161 162
       "disableNotifications": "Désactiver les  notifications",
162 163
       "ok": "OK",
163 164
       "cancel": "Annuler",
164
-      "finished": "Cette machine est terminée. Si vous l'avez l'avez démarée, vous pouvez récupérer votre linge.",
165
+      "finished": "Cette machine est terminée. Si vous l'avez démarrée, vous pouvez récupérer votre linge.",
165 166
       "ready": "Cette machine est vide et prête à être utilisée.",
166 167
       "running": "Cette machine a démarré à %{start} et terminera à %{end}.\nTemps restant : %{remaining} min",
167 168
       "broken": "Cette machine est hors service. Merci pour votre compréhension.",
@@ -171,7 +172,7 @@
171 172
 
172 173
     },
173 174
     "states": {
174
-      "finished": "TERMINE",
175
+      "finished": "TERMINÉ",
175 176
       "ready": "DISPONIBLE",
176 177
       "running": "EN COURS",
177 178
       "broken": "HORS SERVICE",
@@ -195,7 +196,7 @@
195 196
   },
196 197
   "general": {
197 198
     "loading": "Chargement...",
198
-    "networkError": "Impossible de contacter les serveurs. Assurez vous d'être connecté à internet."
199
+    "networkError": "Impossible de contacter les serveurs. Assurez-vous d'être connecté à internet."
199 200
   },
200 201
   "date": {
201 202
     "daysOfWeek": {

Loading…
Cancel
Save