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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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.getInstance().preferences.equipmentShowBanner.current === "1"
  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.getInstance().savePref(
  131. AsyncStorageManager.getInstance().preferences.equipmentShowBanner.key,
  132. '0'
  133. );
  134. this.setState({mascotDialogVisible: false})
  135. };
  136. render() {
  137. return (
  138. <View style={{flex: 1}}>
  139. <AuthenticatedScreen
  140. {...this.props}
  141. ref={this.authRef}
  142. requests={[
  143. {
  144. link: 'location/all',
  145. params: {},
  146. mandatory: true,
  147. },
  148. {
  149. link: 'location/my',
  150. params: {},
  151. mandatory: false,
  152. }
  153. ]}
  154. renderFunction={this.getScreen}
  155. />
  156. <MascotPopup
  157. visible={this.state.mascotDialogVisible}
  158. title={i18n.t("screens.equipment.mascotDialog.title")}
  159. message={i18n.t("screens.equipment.mascotDialog.message")}
  160. icon={"vote"}
  161. buttons={{
  162. action: null,
  163. cancel: {
  164. message: i18n.t("screens.equipment.mascotDialog.button"),
  165. icon: "check",
  166. onPress: this.hideMascotDialog,
  167. }
  168. }}
  169. emotion={MASCOT_STYLE.WINK}
  170. />
  171. </View>
  172. );
  173. }
  174. }
  175. export default withTheme(EquipmentListScreen);