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 11KB

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