Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ProximoListScreen.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // @flow
  2. import * as React from 'react';
  3. import {Body, Container, Content, Left, ListItem, Right, Text, Thumbnail, H1, H3} from 'native-base';
  4. import CustomHeader from "../../components/CustomHeader";
  5. import {FlatList, Platform, View, Image} from "react-native";
  6. import Touchable from 'react-native-platform-touchable';
  7. import Menu, {MenuItem} from 'react-native-material-menu';
  8. import i18n from "i18n-js";
  9. import CustomMaterialIcon from "../../components/CustomMaterialIcon";
  10. import ThemeManager from "../../utils/ThemeManager";
  11. import Modalize from 'react-native-modalize';
  12. const sortMode = {
  13. price: "0",
  14. name: '1',
  15. };
  16. function sortPrice(a, b) {
  17. return a.price - b.price;
  18. }
  19. function sortPriceReverse(a, b) {
  20. return b.price - a.price;
  21. }
  22. function sortName(a, b) {
  23. if (a.name < b.name)
  24. return -1;
  25. if (a.name > b.name)
  26. return 1;
  27. return 0;
  28. }
  29. function sortNameReverse(a, b) {
  30. if (a.name < b.name)
  31. return 1;
  32. if (a.name > b.name)
  33. return -1;
  34. return 0;
  35. }
  36. type Props = {
  37. navigation: Object
  38. }
  39. type State = {
  40. navData: Array<Object>,
  41. currentSortMode: string,
  42. isSortReversed: boolean,
  43. sortPriceIcon: React.Node,
  44. sortNameIcon: React.Node,
  45. modalCurrentDisplayItem: Object,
  46. };
  47. /**
  48. * Class defining proximo's article list of a certain category.
  49. */
  50. export default class ProximoListScreen extends React.Component<Props, State> {
  51. modalRef = React.createRef();
  52. state = {
  53. navData: this.props.navigation.getParam('data', []).sort(sortPrice),
  54. currentSortMode: sortMode.price,
  55. isSortReversed: false,
  56. sortPriceIcon: '',
  57. sortNameIcon: '',
  58. modalCurrentDisplayItem: {}
  59. };
  60. _menu: Menu;
  61. /**
  62. * Saves the reference to the sort menu for later use
  63. *
  64. * @param ref The menu reference
  65. */
  66. setMenuRef = (ref: Menu) => {
  67. this._menu = ref;
  68. };
  69. /**
  70. * Sets the sort mode based on the one selected.
  71. * If the selected mode is the current one, reverse it.
  72. *
  73. * @param mode The string representing the mode
  74. */
  75. sortModeSelected(mode: string) {
  76. let isReverse = this.state.isSortReversed;
  77. if (mode === this.state.currentSortMode) // reverse mode
  78. isReverse = !isReverse; // this.state not updating on this function cycle
  79. else
  80. isReverse = false;
  81. this.setSortMode(mode, isReverse);
  82. }
  83. /**
  84. * Set the current sort mode.
  85. *
  86. * @param mode The string representing the mode
  87. * @param isReverse Whether to use a reverse sort
  88. */
  89. setSortMode(mode: string, isReverse: boolean) {
  90. this.setState({
  91. currentSortMode: mode,
  92. isSortReversed: isReverse
  93. });
  94. let data = this.state.navData;
  95. switch (mode) {
  96. case sortMode.price:
  97. if (isReverse) {
  98. data.sort(sortPriceReverse);
  99. } else {
  100. data.sort(sortPrice);
  101. }
  102. break;
  103. case sortMode.name:
  104. if (isReverse) {
  105. data.sort(sortNameReverse);
  106. } else {
  107. data.sort(sortName);
  108. }
  109. break;
  110. }
  111. this.setState({
  112. navData: data,
  113. });
  114. this.setupSortIcons(mode, isReverse);
  115. this._menu.hide();
  116. }
  117. /**
  118. * Set the sort mode from state when components are ready
  119. */
  120. componentDidMount() {
  121. this.setSortMode(this.state.currentSortMode, this.state.isSortReversed);
  122. }
  123. /**
  124. * get color depending on quantity available
  125. *
  126. * @param availableStock
  127. * @return
  128. */
  129. getStockColor(availableStock: number) {
  130. let color: string;
  131. if (availableStock > 3)
  132. color = ThemeManager.getCurrentThemeVariables().brandSuccess;
  133. else if (availableStock > 0)
  134. color = ThemeManager.getCurrentThemeVariables().brandWarning;
  135. else
  136. color = ThemeManager.getCurrentThemeVariables().brandDanger;
  137. return color;
  138. }
  139. /**
  140. * Set the sort menu icon based on the given mode.
  141. *
  142. * @param mode The string representing the mode
  143. * @param isReverse Whether to use a reversed icon
  144. */
  145. setupSortIcons(mode: string, isReverse: boolean) {
  146. const downSortIcon =
  147. <CustomMaterialIcon
  148. icon={'sort-descending'}/>;
  149. const upSortIcon =
  150. <CustomMaterialIcon
  151. icon={'sort-ascending'}/>;
  152. switch (mode) {
  153. case sortMode.price:
  154. this.setState({sortNameIcon: ''});
  155. if (isReverse) {
  156. this.setState({sortPriceIcon: upSortIcon});
  157. } else {
  158. this.setState({sortPriceIcon: downSortIcon});
  159. }
  160. break;
  161. case sortMode.name:
  162. this.setState({sortPriceIcon: ''});
  163. if (isReverse) {
  164. this.setState({sortNameIcon: upSortIcon});
  165. } else {
  166. this.setState({sortNameIcon: downSortIcon});
  167. }
  168. break;
  169. }
  170. }
  171. getModalContent() {
  172. return (
  173. <View style={{
  174. flex: 1,
  175. padding: 20
  176. }}>
  177. <H1>{this.state.modalCurrentDisplayItem.name}</H1>
  178. <View style={{
  179. flexDirection: 'row',
  180. width: '100%',
  181. marginTop: 10,
  182. }}>
  183. <H3 style={{
  184. color: this.getStockColor(parseInt(this.state.modalCurrentDisplayItem.quantity)),
  185. }}>
  186. {this.state.modalCurrentDisplayItem.quantity + ' ' + i18n.t('proximoScreen.inStock')}
  187. </H3>
  188. <H3 style={{marginLeft: 'auto'}}>{this.state.modalCurrentDisplayItem.price}€</H3>
  189. </View>
  190. <Content>
  191. <View style={{width: '100%', height: 150, marginTop: 20, marginBottom: 20}}>
  192. <Image style={{flex: 1, resizeMode: "contain"}}
  193. source={{uri: this.state.modalCurrentDisplayItem.image}}/>
  194. </View>
  195. <Text>{this.state.modalCurrentDisplayItem.description}</Text>
  196. </Content>
  197. </View>
  198. );
  199. }
  200. showItemDetails(item: Object) {
  201. this.setState({
  202. modalCurrentDisplayItem: item
  203. });
  204. if (this.modalRef.current) {
  205. this.modalRef.current.open();
  206. }
  207. }
  208. render() {
  209. const nav = this.props.navigation;
  210. const navType = nav.getParam('type', '{name: "Error"}');
  211. return (
  212. <Container>
  213. <Modalize ref={this.modalRef}
  214. adjustToContentHeight
  215. modalStyle={{backgroundColor: ThemeManager.getCurrentThemeVariables().containerBgColor}}>
  216. {this.getModalContent()}
  217. </Modalize>
  218. <CustomHeader hasBackButton={true} navigation={nav} title={navType.name} rightButton={
  219. <Menu
  220. ref={this.setMenuRef}
  221. button={
  222. <Touchable
  223. style={{padding: 6}}
  224. onPress={() =>
  225. this._menu.show()
  226. }>
  227. <CustomMaterialIcon
  228. color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
  229. icon={'sort'}/>
  230. </Touchable>
  231. }
  232. >
  233. <MenuItem
  234. onPress={() => this.sortModeSelected(sortMode.name)}>
  235. {this.state.sortNameIcon}
  236. {i18n.t('proximoScreen.sortName')}
  237. </MenuItem>
  238. <MenuItem
  239. onPress={() => this.sortModeSelected(sortMode.price)}>
  240. {this.state.sortPriceIcon}
  241. {i18n.t('proximoScreen.sortPrice')}
  242. </MenuItem>
  243. </Menu>
  244. }/>
  245. <Content>
  246. <FlatList
  247. data={this.state.navData}
  248. extraData={this.state.navData}
  249. keyExtractor={(item) => item.name}
  250. style={{minHeight: 300, width: '100%'}}
  251. renderItem={({item}) =>
  252. <ListItem
  253. thumbnail
  254. onPress={() => {
  255. this.showItemDetails(item);
  256. }}
  257. >
  258. <Left>
  259. <Thumbnail square source={{uri: item.image}}/>
  260. </Left>
  261. <Body>
  262. <Text style={{marginLeft: 20}}>
  263. {item.name}
  264. </Text>
  265. <Text note style={{
  266. marginLeft: 20,
  267. color: this.getStockColor(parseInt(item.quantity))
  268. }}>
  269. {item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
  270. </Text>
  271. </Body>
  272. <Right style={{flex: 1}}>
  273. <Text>
  274. {item.price}€
  275. </Text>
  276. </Right>
  277. </ListItem>}
  278. />
  279. </Content>
  280. </Container>
  281. );
  282. }
  283. }