Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
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.

ClubDisplayScreen.js 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // @flow
  2. import * as React from 'react';
  3. import {Linking, ScrollView, View} from 'react-native';
  4. import {Avatar, Button, Card, Chip, Paragraph, withTheme} from 'react-native-paper';
  5. import ImageModal from 'react-native-image-modal';
  6. import i18n from "i18n-js";
  7. import AuthenticatedScreen from "../../../components/Amicale/AuthenticatedScreen";
  8. import CustomHTML from "../../../components/Overrides/CustomHTML";
  9. import CustomTabBar from "../../../components/Tabbar/CustomTabBar";
  10. import type {category, club} from "./ClubListScreen";
  11. import type {CustomTheme} from "../../../managers/ThemeManager";
  12. import {StackNavigationProp} from "@react-navigation/stack";
  13. import {ERROR_TYPE} from "../../../utils/WebData";
  14. type Props = {
  15. navigation: StackNavigationProp,
  16. route: {
  17. params?: {
  18. data?: club,
  19. categories?: Array<category>,
  20. clubId?: number,
  21. }, ...
  22. },
  23. theme: CustomTheme
  24. };
  25. type State = {
  26. imageModalVisible: boolean,
  27. };
  28. const AMICALE_MAIL = "clubs@amicale-insat.fr";
  29. /**
  30. * Class defining a club event information page.
  31. * If called with data and categories navigation parameters, will use those to display the data.
  32. * If called with clubId parameter, will fetch the information on the server
  33. */
  34. class ClubDisplayScreen extends React.Component<Props, State> {
  35. displayData: club | null;
  36. categories: Array<category> | null;
  37. clubId: number;
  38. shouldFetchData: boolean;
  39. state = {
  40. imageModalVisible: false,
  41. };
  42. constructor(props) {
  43. super(props);
  44. if (this.props.route.params != null) {
  45. if (this.props.route.params.data != null && this.props.route.params.categories != null) {
  46. this.displayData = this.props.route.params.data;
  47. this.categories = this.props.route.params.categories;
  48. this.clubId = this.props.route.params.data.id;
  49. this.shouldFetchData = false;
  50. } else if (this.props.route.params.clubId != null) {
  51. this.displayData = null;
  52. this.categories = null;
  53. this.clubId = this.props.route.params.clubId;
  54. this.shouldFetchData = true;
  55. }
  56. }
  57. }
  58. getCategoryName(id: number) {
  59. if (this.categories !== null) {
  60. for (let i = 0; i < this.categories.length; i++) {
  61. if (id === this.categories[i].id)
  62. return this.categories[i].name;
  63. }
  64. }
  65. return "";
  66. }
  67. getCategoriesRender(categories: [number, number]) {
  68. if (this.categories === null)
  69. return null;
  70. let final = [];
  71. for (let i = 0; i < categories.length; i++) {
  72. let cat = categories[i];
  73. if (cat !== null) {
  74. final.push(
  75. <Chip
  76. style={{marginRight: 5}}
  77. key={i.toString()}>
  78. {this.getCategoryName(cat)}
  79. </Chip>
  80. );
  81. }
  82. }
  83. return <View style={{flexDirection: 'row', marginTop: 5}}>{final}</View>;
  84. }
  85. getManagersRender(resp: Array<string>, email: string | null) {
  86. let final = [];
  87. for (let i = 0; i < resp.length; i++) {
  88. final.push(<Paragraph key={i.toString()}>{resp[i]}</Paragraph>)
  89. }
  90. const hasManagers = resp.length > 0;
  91. return (
  92. <Card style={{marginTop: 10, marginBottom: CustomTabBar.TAB_BAR_HEIGHT + 20}}>
  93. <Card.Title
  94. title={i18n.t('clubs.managers')}
  95. subtitle={hasManagers ? i18n.t('clubs.managersSubtitle') : i18n.t('clubs.managersUnavailable')}
  96. left={(props) => <Avatar.Icon
  97. {...props}
  98. style={{backgroundColor: 'transparent'}}
  99. color={hasManagers ? this.props.theme.colors.success : this.props.theme.colors.primary}
  100. icon="account-tie"/>}
  101. />
  102. <Card.Content>
  103. {final}
  104. {this.getEmailButton(email, hasManagers)}
  105. </Card.Content>
  106. </Card>
  107. );
  108. }
  109. getEmailButton(email: string | null, hasManagers: boolean) {
  110. const destinationEmail = email != null && hasManagers
  111. ? email
  112. : AMICALE_MAIL;
  113. const text = email != null && hasManagers
  114. ? i18n.t("clubs.clubContact")
  115. : i18n.t("clubs.amicaleContact");
  116. return (
  117. <Card.Actions>
  118. <Button
  119. icon="email"
  120. mode="contained"
  121. onPress={() => Linking.openURL('mailto:' + destinationEmail)}
  122. style={{marginLeft: 'auto'}}
  123. >
  124. {text}
  125. </Button>
  126. </Card.Actions>
  127. );
  128. }
  129. updateHeaderTitle(data: Object) {
  130. this.props.navigation.setOptions({title: data.name})
  131. }
  132. getScreen = (response: Array<Object>) => {
  133. let data: club = response[0];
  134. this.updateHeaderTitle(data);
  135. if (data != null) {
  136. return (
  137. <ScrollView style={{paddingLeft: 5, paddingRight: 5}}>
  138. {this.getCategoriesRender(data.category)}
  139. {data.logo !== null ?
  140. <View style={{
  141. marginLeft: 'auto',
  142. marginRight: 'auto',
  143. marginTop: 10,
  144. marginBottom: 10,
  145. }}>
  146. <ImageModal
  147. resizeMode="contain"
  148. imageBackgroundColor={this.props.theme.colors.background}
  149. style={{
  150. width: 300,
  151. height: 300,
  152. }}
  153. source={{
  154. uri: data.logo,
  155. }}
  156. />
  157. </View>
  158. : <View/>}
  159. {data.description !== null ?
  160. // Surround description with div to allow text styling if the description is not html
  161. <Card.Content>
  162. <CustomHTML html={data.description}/>
  163. </Card.Content>
  164. : <View/>}
  165. {this.getManagersRender(data.responsibles, data.email)}
  166. </ScrollView>
  167. );
  168. } else
  169. return null;
  170. };
  171. render() {
  172. if (this.shouldFetchData)
  173. return <AuthenticatedScreen
  174. {...this.props}
  175. requests={[
  176. {
  177. link: 'clubs/info',
  178. params: {'id': this.clubId},
  179. mandatory: true
  180. }
  181. ]}
  182. renderFunction={this.getScreen}
  183. errorViewOverride={[
  184. {
  185. errorCode: ERROR_TYPE.BAD_INPUT,
  186. message: i18n.t("clubs.invalidClub"),
  187. icon: "account-question",
  188. showRetryButton: false
  189. }
  190. ]}
  191. />;
  192. else
  193. return this.getScreen([this.displayData]);
  194. }
  195. }
  196. export default withTheme(ClubDisplayScreen);