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.

ProfileScreen.js 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. // @flow
  2. import * as React from 'react';
  3. import {FlatList, StyleSheet, View} from "react-native";
  4. import {Avatar, Button, Card, Divider, List, withTheme} from 'react-native-paper';
  5. import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
  6. import i18n from 'i18n-js';
  7. import LogoutDialog from "../../components/Amicale/LogoutDialog";
  8. import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton";
  9. type Props = {
  10. navigation: Object,
  11. theme: Object,
  12. }
  13. type State = {
  14. dialogVisible: boolean,
  15. }
  16. class ProfileScreen extends React.Component<Props, State> {
  17. state = {
  18. dialogVisible: false,
  19. };
  20. data: Object;
  21. flatListData: Array<Object>;
  22. constructor() {
  23. super();
  24. this.flatListData = [
  25. {id: '0'},
  26. {id: '1'},
  27. {id: '2'},
  28. ]
  29. }
  30. componentDidMount() {
  31. this.props.navigation.setOptions({
  32. headerRight: this.getHeaderButton,
  33. });
  34. }
  35. showDisconnectDialog = () => this.setState({dialogVisible: true});
  36. hideDisconnectDialog = () => this.setState({dialogVisible: false});
  37. getHeaderButton = () => <MaterialHeaderButtons>
  38. <Item title="logout" iconName="logout" onPress={this.showDisconnectDialog}/>
  39. </MaterialHeaderButtons>;
  40. getScreen = (data: Object) => {
  41. this.data = data[0];
  42. return (
  43. <View>
  44. {/*$FlowFixMe*/}
  45. <FlatList
  46. renderItem={this.getRenderItem}
  47. data={this.flatListData}
  48. />
  49. <LogoutDialog
  50. {...this.props}
  51. visible={this.state.dialogVisible}
  52. onDismiss={this.hideDisconnectDialog}
  53. />
  54. </View>
  55. )
  56. };
  57. getRenderItem = ({item}: Object) => {
  58. switch (item.id) {
  59. case '0':
  60. return this.getPersonalCard();
  61. case '1':
  62. return this.getClubCard();
  63. default:
  64. return this.getMembershipCar();
  65. }
  66. };
  67. /**
  68. * Checks if the given field is available
  69. *
  70. * @param field The field to check
  71. * @return {boolean}
  72. */
  73. isFieldAvailable(field: ?string) {
  74. return field !== null;
  75. }
  76. /**
  77. * Gets the given field value.
  78. * If the field does not have a value, returns a placeholder text
  79. *
  80. * @param field The field to get the value from
  81. * @return {*}
  82. */
  83. getFieldValue(field: ?string) {
  84. return this.isFieldAvailable(field)
  85. ? field
  86. : i18n.t("profileScreen.noData");
  87. }
  88. /**
  89. * Gets a list item showing personal information
  90. *
  91. * @param field The field to display
  92. * @param icon The icon to use
  93. * @return {*}
  94. */
  95. getPersonalListItem(field: ?string, icon: string) {
  96. let title = this.isFieldAvailable(field) ? this.getFieldValue(field) : ':(';
  97. let subtitle = this.isFieldAvailable(field) ? '' : this.getFieldValue(field);
  98. return (
  99. <List.Item
  100. title={title}
  101. description={subtitle}
  102. left={props => <List.Icon
  103. {...props}
  104. icon={icon}
  105. color={this.isFieldAvailable(field) ? undefined : this.props.theme.colors.textDisabled}
  106. />}
  107. />
  108. );
  109. }
  110. /**
  111. * Gets a card containing user personal information
  112. *
  113. * @return {*}
  114. */
  115. getPersonalCard() {
  116. return (
  117. <Card style={styles.card}>
  118. <Card.Title
  119. title={this.data.first_name + ' ' + this.data.last_name}
  120. subtitle={this.data.email}
  121. left={(props) => <Avatar.Icon
  122. {...props}
  123. icon="account"
  124. color={this.props.theme.colors.primary}
  125. style={styles.icon}
  126. />}
  127. />
  128. <Card.Content>
  129. <Divider/>
  130. <List.Section>
  131. <List.Subheader>{i18n.t("profileScreen.personalInformation")}</List.Subheader>
  132. {this.getPersonalListItem(this.data.birthday, "cake-variant")}
  133. {this.getPersonalListItem(this.data.phone, "phone")}
  134. {this.getPersonalListItem(this.data.email, "email")}
  135. {this.getPersonalListItem(this.data.branch, "school")}
  136. </List.Section>
  137. <Divider/>
  138. <Card.Actions>
  139. <Button
  140. icon="account-edit"
  141. mode="contained"
  142. onPress={() => this.props.navigation.navigate('amicale-website', {
  143. screen: 'amicale-website',
  144. params: {path: this.data.link}
  145. })}
  146. style={styles.editButton}>
  147. {i18n.t("profileScreen.editInformation")}
  148. </Button>
  149. </Card.Actions>
  150. </Card.Content>
  151. </Card>
  152. );
  153. }
  154. /**
  155. * Gets a cars containing clubs the user is part of
  156. *
  157. * @return {*}
  158. */
  159. getClubCard() {
  160. return (
  161. <Card style={styles.card}>
  162. <Card.Title
  163. title={i18n.t("profileScreen.clubs")}
  164. subtitle={i18n.t("profileScreen.clubsSubtitle")}
  165. left={(props) => <Avatar.Icon
  166. {...props}
  167. icon="account-group"
  168. color={this.props.theme.colors.primary}
  169. style={styles.icon}
  170. />}
  171. />
  172. <Card.Content>
  173. <Divider/>
  174. {this.getClubList(this.data.clubs)}
  175. </Card.Content>
  176. </Card>
  177. );
  178. }
  179. /**
  180. * Gets a card showing if the user has payed his membership
  181. *
  182. * @return {*}
  183. */
  184. getMembershipCar() {
  185. return (
  186. <Card style={styles.card}>
  187. <Card.Title
  188. title={i18n.t("profileScreen.membership")}
  189. subtitle={i18n.t("profileScreen.membershipSubtitle")}
  190. left={(props) => <Avatar.Icon
  191. {...props}
  192. icon="credit-card"
  193. color={this.props.theme.colors.primary}
  194. style={styles.icon}
  195. />}
  196. />
  197. <Card.Content>
  198. <List.Section>
  199. {this.getMembershipItem(this.data.validity)}
  200. </List.Section>
  201. </Card.Content>
  202. </Card>
  203. );
  204. }
  205. /**
  206. * Gets the item showing if the user has payed his membership
  207. *
  208. * @return {*}
  209. */
  210. getMembershipItem(state: boolean) {
  211. return (
  212. <List.Item
  213. title={state ? i18n.t("profileScreen.membershipPayed") : i18n.t("profileScreen.membershipNotPayed")}
  214. left={props => <List.Icon
  215. {...props}
  216. color={state ? this.props.theme.colors.success : this.props.theme.colors.danger}
  217. icon={state ? 'check' : 'close'}
  218. />}
  219. />
  220. );
  221. }
  222. /**
  223. * Opens the club details screen for the club of given ID
  224. * @param id The club's id to open
  225. */
  226. openClubDetailsScreen(id: number) {
  227. this.props.navigation.navigate("club-information", {clubId: id});
  228. }
  229. /**
  230. * Gets a list item for the club list
  231. *
  232. * @param item The club to render
  233. * @return {*}
  234. */
  235. clubListItem = ({item}: Object) => {
  236. const onPress = () => this.openClubDetailsScreen(item.id);
  237. let description = i18n.t("profileScreen.isMember");
  238. let icon = (props) => <List.Icon {...props} icon="chevron-right"/>;
  239. if (item.is_manager) {
  240. description = i18n.t("profileScreen.isManager");
  241. icon = (props) => <List.Icon {...props} icon="star" color={this.props.theme.colors.primary}/>;
  242. }
  243. return <List.Item
  244. title={item.name}
  245. description={description}
  246. left={icon}
  247. onPress={onPress}
  248. />;
  249. };
  250. clubKeyExtractor = (item: Object) => item.name;
  251. sortClubList = (a: Object, b: Object) => a.is_manager ? -1 : 1;
  252. /**
  253. * Renders the list of clubs the user is part of
  254. *
  255. * @param list The club list
  256. * @return {*}
  257. */
  258. getClubList(list: Array<Object>) {
  259. list.sort(this.sortClubList);
  260. return (
  261. //$FlowFixMe
  262. <FlatList
  263. renderItem={this.clubListItem}
  264. keyExtractor={this.clubKeyExtractor}
  265. data={list}
  266. />
  267. );
  268. }
  269. render() {
  270. return (
  271. <AuthenticatedScreen
  272. {...this.props}
  273. requests={[
  274. {
  275. link: 'user/profile',
  276. params: {},
  277. mandatory: true,
  278. }
  279. ]}
  280. renderFunction={this.getScreen}
  281. />
  282. );
  283. }
  284. }
  285. const styles = StyleSheet.create({
  286. card: {
  287. margin: 10,
  288. },
  289. icon: {
  290. backgroundColor: 'transparent'
  291. },
  292. editButton: {
  293. marginLeft: 'auto'
  294. }
  295. });
  296. export default withTheme(ProfileScreen);