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.

ServicesScreen.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. // @flow
  2. import * as React from 'react';
  3. import type {cardList} from "../../components/Lists/CardList/CardList";
  4. import CardList from "../../components/Lists/CardList/CardList";
  5. import CustomTabBar from "../../components/Tabbar/CustomTabBar";
  6. import {withCollapsible} from "../../utils/withCollapsible";
  7. import {Collapsible} from "react-navigation-collapsible";
  8. import {CommonActions} from "@react-navigation/native";
  9. import {Animated, View} from "react-native";
  10. import {Avatar, Button, Card, Divider, List, Title, TouchableRipple, withTheme} from "react-native-paper";
  11. import type {CustomTheme} from "../../managers/ThemeManager";
  12. import ConnectionManager from "../../managers/ConnectionManager";
  13. import i18n from 'i18n-js';
  14. import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton";
  15. type Props = {
  16. navigation: Object,
  17. route: Object,
  18. collapsibleStack: Collapsible,
  19. theme: CustomTheme,
  20. }
  21. const CLUBS_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Clubs.png";
  22. const PROFILE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ProfilAmicaliste.png";
  23. const VOTE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Vote.png";
  24. const AMICALE_IMAGE = require("../../../assets/amicale.png");
  25. const PROXIMO_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Proximo.png"
  26. const WIKETUD_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Wiketud.png";
  27. const EE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/EEC.png";
  28. const TUTORINSA_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/TutorINSA.png";
  29. const MAP_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Map.png";
  30. const BIB_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Bib.png";
  31. const RU_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/RU.png";
  32. const ROOM_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Salles.png";
  33. const EMAIL_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Bluemind.png";
  34. const ENT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ENT.png";
  35. export type listItem = {
  36. title: string,
  37. description: string,
  38. image: string | number,
  39. shouldLogin: boolean,
  40. content: cardList,
  41. }
  42. type State = {
  43. isLoggedIn: boolean,
  44. }
  45. // TODO translate subtitles
  46. class ServicesScreen extends React.Component<Props, State> {
  47. amicaleDataset: cardList;
  48. studentsDataset: cardList;
  49. insaDataset: cardList;
  50. finalDataset: Array<listItem>
  51. constructor(props) {
  52. super(props);
  53. const nav = props.navigation;
  54. this.amicaleDataset = [
  55. {
  56. title: i18n.t('screens.clubsAbout'),
  57. subtitle: "CLUB LIST",
  58. image: CLUBS_IMAGE,
  59. onPress: () => nav.navigate("club-list"),
  60. },
  61. {
  62. title: i18n.t('screens.profile'),
  63. subtitle: "PROFIL",
  64. image: PROFILE_IMAGE,
  65. onPress: () => nav.navigate("profile"),
  66. },
  67. {
  68. title: i18n.t('screens.amicaleWebsite'),
  69. subtitle: "AMICALE",
  70. image: AMICALE_IMAGE,
  71. onPress: () => nav.navigate("amicale-website"),
  72. },
  73. {
  74. title: i18n.t('screens.vote'),
  75. subtitle: "ELECTIONS",
  76. image: VOTE_IMAGE,
  77. onPress: () => nav.navigate("vote"),
  78. },
  79. ];
  80. this.studentsDataset = [
  81. {
  82. title: i18n.t('screens.proximo'),
  83. subtitle: "proximo",
  84. image: PROXIMO_IMAGE,
  85. onPress: () => nav.navigate("proximo"),
  86. },
  87. {
  88. title: "Wiketud",
  89. subtitle: "wiketud",
  90. image: WIKETUD_IMAGE,
  91. onPress: () => nav.navigate("wiketud"),
  92. },
  93. {
  94. title: "Élus Étudiants",
  95. subtitle: "ELUS ETUDIANTS",
  96. image: EE_IMAGE,
  97. onPress: () => nav.navigate("elus-etudiants"),
  98. },
  99. {
  100. title: "Tutor'INSA",
  101. subtitle: "TUTOR INSA",
  102. image: TUTORINSA_IMAGE,
  103. onPress: () => nav.navigate("tutorinsa"),
  104. },
  105. {
  106. title: i18n.t('screens.amicaleWebsite'),
  107. subtitle: "AMICALE",
  108. image: AMICALE_IMAGE,
  109. onPress: () => nav.navigate("amicale-website"),
  110. },
  111. ];
  112. this.insaDataset = [
  113. {
  114. title: i18n.t('screens.map'),
  115. subtitle: "MAP",
  116. image: MAP_IMAGE,
  117. onPress: () => nav.navigate("map"),
  118. },
  119. {
  120. title: i18n.t('screens.menuSelf'),
  121. subtitle: "the ru",
  122. image: RU_IMAGE,
  123. onPress: () => nav.navigate("self-menu"),
  124. },
  125. {
  126. title: i18n.t('screens.availableRooms'),
  127. subtitle: "ROOMS",
  128. image: ROOM_IMAGE,
  129. onPress: () => nav.navigate("available-rooms"),
  130. },
  131. {
  132. title: i18n.t('screens.bib'),
  133. subtitle: "BIB",
  134. image: BIB_IMAGE,
  135. onPress: () => nav.navigate("bib"),
  136. },
  137. {
  138. title: i18n.t('screens.bluemind'),
  139. subtitle: "EMAIL",
  140. image: EMAIL_IMAGE,
  141. onPress: () => nav.navigate("bluemind"),
  142. },
  143. {
  144. title: i18n.t('screens.ent'),
  145. subtitle: "ENT",
  146. image: ENT_IMAGE,
  147. onPress: () => nav.navigate("ent"),
  148. },
  149. ];
  150. this.finalDataset = [
  151. {
  152. title: i18n.t("servicesScreen.amicale"),
  153. description: "LOGIN",
  154. image: AMICALE_IMAGE,
  155. shouldLogin: true,
  156. content: this.amicaleDataset
  157. },
  158. {
  159. title: i18n.t("servicesScreen.students"),
  160. description: "SERVICES OFFERED BY STUDENTS",
  161. image: 'account-group',
  162. shouldLogin: false,
  163. content: this.studentsDataset
  164. },
  165. {
  166. title: i18n.t("servicesScreen.insa"),
  167. description: "SERVICES OFFERED BY INSA",
  168. image: 'school',
  169. shouldLogin: false,
  170. content: this.insaDataset
  171. },
  172. ];
  173. this.state = {
  174. isLoggedIn: ConnectionManager.getInstance().isLoggedIn()
  175. }
  176. }
  177. componentDidMount() {
  178. this.props.navigation.addListener('focus', this.onFocus);
  179. this.props.navigation.setOptions({
  180. headerRight: this.getAboutButton,
  181. });
  182. }
  183. getAboutButton = () =>
  184. <MaterialHeaderButtons>
  185. <Item title="information" iconName="information" onPress={this.onAboutPress}/>
  186. </MaterialHeaderButtons>;
  187. onAboutPress = () => this.props.navigation.navigate('amicale-contact');
  188. onFocus = () => {
  189. this.handleNavigationParams();
  190. this.setState({isLoggedIn: ConnectionManager.getInstance().isLoggedIn()})
  191. }
  192. handleNavigationParams() {
  193. if (this.props.route.params != null) {
  194. if (this.props.route.params.nextScreen != null) {
  195. this.props.navigation.navigate(this.props.route.params.nextScreen);
  196. // reset params to prevent infinite loop
  197. this.props.navigation.dispatch(CommonActions.setParams({nextScreen: null}));
  198. }
  199. }
  200. };
  201. getAvatar(props, source: string | number) {
  202. if (typeof source === "number")
  203. return <Avatar.Image
  204. {...props}
  205. size={48}
  206. source={source}
  207. style={{backgroundColor: 'transparent'}}
  208. />
  209. else
  210. return <Avatar.Icon
  211. {...props}
  212. size={48}
  213. icon={source}
  214. color={this.props.theme.colors.primary}
  215. style={{backgroundColor: 'transparent'}}
  216. />
  217. }
  218. getLoginMessage() {
  219. return (
  220. <View>
  221. <Title style={{
  222. marginLeft: 'auto',
  223. marginRight: 'auto',
  224. }}>
  225. {i18n.t("servicesScreen.notLoggedIn")}
  226. </Title>
  227. <Button
  228. icon="login"
  229. mode="contained"
  230. onPress={() => this.props.navigation.navigate("login")}
  231. style={{
  232. marginLeft: 'auto',
  233. marginRight: 'auto',
  234. }}>
  235. {i18n.t("screens.login")}
  236. </Button>
  237. </View>
  238. )
  239. }
  240. renderItem = ({item}: { item: listItem }) => {
  241. const shouldShowLogin = !this.state.isLoggedIn && item.shouldLogin;
  242. return (
  243. <TouchableRipple
  244. style={{
  245. margin: 5,
  246. marginBottom: 20,
  247. }}
  248. onPress={shouldShowLogin
  249. ? undefined
  250. : () => this.props.navigation.navigate("services-section", {data: item})}
  251. >
  252. <View>
  253. <Card.Title
  254. title={item.title}
  255. left={(props) => this.getAvatar(props, item.image)}
  256. right={shouldShowLogin
  257. ? undefined
  258. : (props) => <List.Icon {...props} icon="chevron-right"/>}
  259. />
  260. {
  261. shouldShowLogin
  262. ? this.getLoginMessage()
  263. : <CardList
  264. dataset={item.content}
  265. isHorizontal={true}
  266. />
  267. }
  268. </View>
  269. </TouchableRipple>
  270. );
  271. };
  272. keyExtractor = (item: listItem) => {
  273. return item.title;
  274. }
  275. render() {
  276. const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
  277. return <Animated.FlatList
  278. data={this.finalDataset}
  279. renderItem={this.renderItem}
  280. keyExtractor={this.keyExtractor}
  281. onScroll={onScroll}
  282. contentContainerStyle={{
  283. paddingTop: containerPaddingTop,
  284. paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
  285. }}
  286. scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
  287. ItemSeparatorComponent={() => <Divider/>}
  288. />
  289. }
  290. }
  291. export default withCollapsible(withTheme(ServicesScreen));