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.

EquipmentListScreen.js 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // @flow
  2. import * as React from 'react';
  3. import {View} from "react-native";
  4. import {Button, withTheme} from 'react-native-paper';
  5. import AuthenticatedScreen from "../../../components/Amicale/AuthenticatedScreen";
  6. import {StackNavigationProp} from "@react-navigation/stack";
  7. import type {CustomTheme} from "../../../managers/ThemeManager";
  8. import i18n from "i18n-js";
  9. import type {club} from "../Clubs/ClubListScreen";
  10. import EquipmentListItem from "../../../components/Lists/Equipment/EquipmentListItem";
  11. import MascotPopup from "../../../components/Mascot/MascotPopup";
  12. import {MASCOT_STYLE} from "../../../components/Mascot/Mascot";
  13. import AsyncStorageManager from "../../../managers/AsyncStorageManager";
  14. import CollapsibleFlatList from "../../../components/Collapsible/CollapsibleFlatList";
  15. type Props = {
  16. navigation: StackNavigationProp,
  17. theme: CustomTheme,
  18. }
  19. type State = {
  20. mascotDialogVisible: boolean,
  21. }
  22. export type Device = {
  23. id: number,
  24. name: string,
  25. caution: number,
  26. booked_at: Array<{ begin: string, end: string }>,
  27. };
  28. export type RentedDevice = {
  29. device_id: number,
  30. device_name: string,
  31. begin: string,
  32. end: string,
  33. }
  34. const LIST_ITEM_HEIGHT = 64;
  35. class EquipmentListScreen extends React.Component<Props, State> {
  36. state = {
  37. mascotDialogVisible: AsyncStorageManager.getBool(AsyncStorageManager.PREFERENCES.equipmentShowBanner.key),
  38. }
  39. data: Array<Device>;
  40. userRents: Array<RentedDevice>;
  41. authRef: { current: null | AuthenticatedScreen };
  42. canRefresh: boolean;
  43. constructor(props: Props) {
  44. super(props);
  45. this.canRefresh = false;
  46. this.authRef = React.createRef();
  47. this.props.navigation.addListener('focus', this.onScreenFocus);
  48. }
  49. onScreenFocus = () => {
  50. if (this.canRefresh && this.authRef.current != null)
  51. this.authRef.current.reload();
  52. this.canRefresh = true;
  53. };
  54. getRenderItem = ({item}: { item: Device }) => {
  55. return (
  56. <EquipmentListItem
  57. navigation={this.props.navigation}
  58. item={item}
  59. userDeviceRentDates={this.getUserDeviceRentDates(item)}
  60. height={LIST_ITEM_HEIGHT}/>
  61. );
  62. };
  63. getUserDeviceRentDates(item: Device) {
  64. let dates = null;
  65. for (let i = 0; i < this.userRents.length; i++) {
  66. let device = this.userRents[i];
  67. if (item.id === device.device_id) {
  68. dates = [device.begin, device.end];
  69. break;
  70. }
  71. }
  72. return dates;
  73. }
  74. /**
  75. * Gets the list header, with explains this screen's purpose
  76. *
  77. * @returns {*}
  78. */
  79. getListHeader() {
  80. return (
  81. <View style={{
  82. width: "100%",
  83. marginTop: 10,
  84. marginBottom: 10,
  85. }}>
  86. <Button
  87. mode={"contained"}
  88. icon={"help-circle"}
  89. onPress={this.showMascotDialog}
  90. style={{
  91. marginRight: "auto",
  92. marginLeft: "auto",
  93. }}>
  94. {i18n.t("screens.equipment.mascotDialog.title")}
  95. </Button>
  96. </View>
  97. );
  98. }
  99. keyExtractor = (item: club) => item.id.toString();
  100. /**
  101. * Gets the main screen component with the fetched data
  102. *
  103. * @param data The data fetched from the server
  104. * @returns {*}
  105. */
  106. getScreen = (data: Array<{ [key: string]: any } | null>) => {
  107. if (data[0] != null) {
  108. const fetchedData = data[0];
  109. if (fetchedData != null)
  110. this.data = fetchedData["devices"];
  111. }
  112. if (data[1] != null) {
  113. const fetchedData = data[1];
  114. if (fetchedData != null)
  115. this.userRents = fetchedData["locations"];
  116. }
  117. return (
  118. <CollapsibleFlatList
  119. keyExtractor={this.keyExtractor}
  120. renderItem={this.getRenderItem}
  121. ListHeaderComponent={this.getListHeader()}
  122. data={this.data}
  123. />
  124. )
  125. };
  126. showMascotDialog = () => {
  127. this.setState({mascotDialogVisible: true})
  128. };
  129. hideMascotDialog = () => {
  130. AsyncStorageManager.set(AsyncStorageManager.PREFERENCES.equipmentShowBanner.key, false);
  131. this.setState({mascotDialogVisible: false})
  132. };
  133. render() {
  134. return (
  135. <View style={{flex: 1}}>
  136. <AuthenticatedScreen
  137. {...this.props}
  138. ref={this.authRef}
  139. requests={[
  140. {
  141. link: 'location/all',
  142. params: {},
  143. mandatory: true,
  144. },
  145. {
  146. link: 'location/my',
  147. params: {},
  148. mandatory: false,
  149. }
  150. ]}
  151. renderFunction={this.getScreen}
  152. />
  153. <MascotPopup
  154. visible={this.state.mascotDialogVisible}
  155. title={i18n.t("screens.equipment.mascotDialog.title")}
  156. message={i18n.t("screens.equipment.mascotDialog.message")}
  157. icon={"vote"}
  158. buttons={{
  159. action: null,
  160. cancel: {
  161. message: i18n.t("screens.equipment.mascotDialog.button"),
  162. icon: "check",
  163. onPress: this.hideMascotDialog,
  164. }
  165. }}
  166. emotion={MASCOT_STYLE.WINK}
  167. />
  168. </View>
  169. );
  170. }
  171. }
  172. export default withTheme(EquipmentListScreen);