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.

ProxiwashScreen.js 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import React from 'react';
  2. import {SectionList, RefreshControl, View} from 'react-native';
  3. import {Body, Container, Icon, Left, ListItem, Right, Text, Toast, H2, Button} from 'native-base';
  4. import CustomHeader from "../components/CustomHeader";
  5. import ThemeManager from '../utils/ThemeManager';
  6. import NotificationsManager from '../utils/NotificationsManager';
  7. import i18n from "i18n-js";
  8. import {AsyncStorage} from 'react-native'
  9. import CustomMaterialIcon from "../components/CustomMaterialIcon";
  10. const DATA_URL = "https://etud.insa-toulouse.fr/~vergnet/appli-amicale/dataProxiwash.json";
  11. const WATCHED_MACHINES_PREFKEY = "proxiwash.watchedMachines";
  12. const remainderNotifTime = 5;
  13. const MACHINE_STATES = {
  14. TERMINE: "0",
  15. DISPONIBLE: "1",
  16. FONCTIONNE: "2",
  17. HS: "3",
  18. ERREUR: "4"
  19. };
  20. let stateStrings = {};
  21. let stateColors = {};
  22. export default class ProxiwashScreen extends React.Component {
  23. constructor(props) {
  24. super(props);
  25. let colors = ThemeManager.getInstance().getCurrentThemeVariables();
  26. stateColors[MACHINE_STATES.TERMINE] = colors.proxiwashFinishedColor;
  27. stateColors[MACHINE_STATES.DISPONIBLE] = colors.proxiwashReadyColor;
  28. stateColors[MACHINE_STATES.FONCTIONNE] = colors.proxiwashRunningColor;
  29. stateColors[MACHINE_STATES.HS] = colors.proxiwashBrokenColor;
  30. stateColors[MACHINE_STATES.ERREUR] = colors.proxiwashErrorColor;
  31. stateStrings[MACHINE_STATES.TERMINE] = i18n.t('proxiwashScreen.states.finished');
  32. stateStrings[MACHINE_STATES.DISPONIBLE] = i18n.t('proxiwashScreen.states.ready');
  33. stateStrings[MACHINE_STATES.FONCTIONNE] = i18n.t('proxiwashScreen.states.running');
  34. stateStrings[MACHINE_STATES.HS] = i18n.t('proxiwashScreen.states.broken');
  35. stateStrings[MACHINE_STATES.ERREUR] = i18n.t('proxiwashScreen.states.error');
  36. this.state = {
  37. refreshing: false,
  38. firstLoading: true,
  39. data: {},
  40. machinesWatched: [],
  41. };
  42. }
  43. async readData() {
  44. try {
  45. let response = await fetch(DATA_URL);
  46. let responseJson = await response.json();
  47. // This prevents end notifications from showing
  48. // let watchList = this.state.machinesWatched;
  49. // for (let i = 0; i < watchList.length; i++) {
  50. // if (responseJson[MACHINE_STATES[watchList[i].machineNumber.state]] !== MACHINE_STATES.FONCTIONNE)
  51. // this.disableNotification(watchList[i].machineNumber);
  52. // }
  53. this.setState({
  54. data: responseJson
  55. });
  56. } catch (error) {
  57. console.error(error);
  58. }
  59. }
  60. async componentWillMount() {
  61. let dataString = await AsyncStorage.getItem(WATCHED_MACHINES_PREFKEY);
  62. if (dataString === null)
  63. dataString = '[]';
  64. this.setState({machinesWatched: JSON.parse(dataString)});
  65. }
  66. componentDidMount() {
  67. this._onRefresh();
  68. }
  69. _onRefresh = () => {
  70. this.setState({refreshing: true});
  71. this.readData().then(() => {
  72. this.setState({
  73. refreshing: false,
  74. firstLoading: false
  75. });
  76. Toast.show({
  77. text: i18n.t('proxiwashScreen.listUpdated'),
  78. buttonText: 'OK',
  79. type: "success",
  80. duration: 2000
  81. })
  82. });
  83. };
  84. static getRemainingTime(startString, endString, percentDone) {
  85. let startArray = startString.split(':');
  86. let endArray = endString.split(':');
  87. let startDate = new Date();
  88. startDate.setHours(parseInt(startArray[0]), parseInt(startArray[1]), 0, 0);
  89. let endDate = new Date();
  90. endDate.setHours(parseInt(endArray[0]), parseInt(endArray[1]), 0, 0);
  91. return (((100 - percentDone) / 100) * (endDate - startDate) / (60 * 1000)).toFixed(0); // Convert milliseconds into minutes
  92. }
  93. async setupNotifications(number, remainingTime) {
  94. if (!this.isMachineWatched(number)) {
  95. let endNotifID = await NotificationsManager.scheduleNotification(
  96. i18n.t('proxiwashScreen.notifications.machineFinishedTitle'),
  97. i18n.t('proxiwashScreen.notifications.machineFinishedBody', {number: number}),
  98. new Date().getTime() + remainingTime * (60 * 1000) // Convert back to milliseconds
  99. );
  100. let remainderNotifID = undefined;
  101. if (remainingTime > remainderNotifTime) {
  102. remainderNotifID = await NotificationsManager.scheduleNotification(
  103. i18n.t('proxiwashScreen.notifications.machineRunningTitle', {time: remainderNotifTime}),
  104. i18n.t('proxiwashScreen.notifications.machineRunningBody', {number: number}),
  105. new Date().getTime() + (remainingTime - remainderNotifTime) * (60 * 1000) // Convert back to milliseconds
  106. );
  107. }
  108. let data = this.state.machinesWatched;
  109. data.push({machineNumber: number, endNotifID: endNotifID, remainderNotifID: remainderNotifID});
  110. this.setState({machinesWatched: data});
  111. AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data));
  112. } else
  113. this.disableNotification(number);
  114. }
  115. disableNotification(number) {
  116. let data = this.state.machinesWatched;
  117. if (data.length > 0) {
  118. let elem = this.state.machinesWatched.find(function (elem) {
  119. return elem.machineNumber === number
  120. });
  121. let arrayIndex = data.indexOf(elem);
  122. NotificationsManager.cancelScheduledNoification(data[arrayIndex].endNotifID);
  123. if (data[arrayIndex].remainderNotifID !== undefined)
  124. NotificationsManager.cancelScheduledNoification(data[arrayIndex].remainderNotifID);
  125. data.splice(arrayIndex, 1);
  126. this.setState({machinesWatched: data});
  127. AsyncStorage.setItem(WATCHED_MACHINES_PREFKEY, JSON.stringify(data));
  128. }
  129. }
  130. isMachineWatched(number) {
  131. return this.state.machinesWatched.find(function (elem) {
  132. return elem.machineNumber === number
  133. }) !== undefined;
  134. }
  135. renderItem(item, section, data) {
  136. return (
  137. <ListItem
  138. thumbnail
  139. style={{
  140. marginLeft: 0,
  141. backgroundColor: stateColors[MACHINE_STATES[item.state]]
  142. }}
  143. >
  144. <View style={{
  145. height: '100%',
  146. position: 'absolute',
  147. alignSelf: 'flex-end',
  148. right: 0,
  149. width: item.donePercent !== '' ? (100 - parseInt(item.donePercent)).toString() + '%' : 0,
  150. backgroundColor: ThemeManager.getInstance().getCurrentThemeVariables().containerBgColor
  151. }}>
  152. </View>
  153. <Left>
  154. <CustomMaterialIcon icon={section.title === data[0].title ? 'tumble-dryer' : 'washing-machine'}
  155. fontSize={30}
  156. />
  157. </Left>
  158. <Body>
  159. <Text>
  160. {section.title === data[0].title ? i18n.t('proxiwashScreen.dryer') : i18n.t('proxiwashScreen.washer')} n°{item.number}
  161. </Text>
  162. <Text note>
  163. {item.startTime !== '' ? item.startTime + '/' + item.endTime : ''}
  164. </Text>
  165. </Body>
  166. <Right>
  167. {item.startTime !== '' ?
  168. <Button
  169. style={this.isMachineWatched(item.number) ?
  170. {backgroundColor: '#ba7c1f'} : {}}
  171. onPress={() => {
  172. this.setupNotifications(item.number, ProxiwashScreen.getRemainingTime(item.startTime, item.endTime, item.donePercent))
  173. }}>
  174. <Text>
  175. {ProxiwashScreen.getRemainingTime(item.startTime, item.endTime, item.donePercent) + ' ' + i18n.t('proxiwashScreen.min')}
  176. </Text>
  177. <Icon name={this.isMachineWatched(item.number) ? 'bell-ring' : 'bell'}
  178. type={'MaterialCommunityIcons'}
  179. style={{fontSize: 30, width: 30}}
  180. />
  181. </Button>
  182. : <Text style={MACHINE_STATES[item.state] === MACHINE_STATES.TERMINE ?
  183. {fontWeight: 'bold'} : {}}
  184. >{stateStrings[MACHINE_STATES[item.state]]}</Text>
  185. }
  186. </Right>
  187. </ListItem>);
  188. }
  189. render() {
  190. const nav = this.props.navigation;
  191. const data = [
  192. {
  193. title: i18n.t('proxiwashScreen.dryers'),
  194. data: this.state.data.dryers === undefined ? [] : this.state.data.dryers,
  195. extraData: this.state
  196. },
  197. {
  198. title: i18n.t('proxiwashScreen.washers'),
  199. data: this.state.data.washers === undefined ? [] : this.state.data.washers,
  200. extraData: this.state
  201. },
  202. ];
  203. const loadingData = [
  204. {
  205. title: i18n.t('proxiwashScreen.loading'),
  206. data: []
  207. }
  208. ];
  209. return (
  210. <Container>
  211. <CustomHeader navigation={nav} title={'Proxiwash'}/>
  212. <SectionList
  213. sections={this.state.firstLoading ? loadingData : data}
  214. keyExtractor={(item) => item.number}
  215. refreshControl={
  216. <RefreshControl
  217. refreshing={this.state.refreshing}
  218. onRefresh={this._onRefresh}
  219. />
  220. }
  221. renderSectionHeader={({section: {title}}) => (
  222. <H2 style={{textAlign: 'center', paddingVertical: 10}}>{title}</H2>
  223. )}
  224. renderItem={({item, section}) =>
  225. this.renderItem(item, section, data)
  226. }
  227. />
  228. </Container>
  229. );
  230. }
  231. }