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.

ServicesScreen.tsx 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2019 - 2020 Arnaud Vergnet.
  3. *
  4. * This file is part of Campus INSAT.
  5. *
  6. * Campus INSAT is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Campus INSAT is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. import React, { useLayoutEffect } from 'react';
  20. import { Image, StyleSheet, View } from 'react-native';
  21. import {
  22. Avatar,
  23. Card,
  24. Divider,
  25. List,
  26. TouchableRipple,
  27. useTheme,
  28. } from 'react-native-paper';
  29. import i18n from 'i18n-js';
  30. import CardList from '../../components/Lists/CardList/CardList';
  31. import MaterialHeaderButtons, {
  32. Item,
  33. } from '../../components/Overrides/CustomHeaderButton';
  34. import { MASCOT_STYLE } from '../../components/Mascot/Mascot';
  35. import MascotPopup from '../../components/Mascot/MascotPopup';
  36. import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
  37. import {
  38. getCategories,
  39. ServiceCategoryType,
  40. SERVICES_CATEGORIES_KEY,
  41. } from '../../utils/Services';
  42. import { useNavigation } from '@react-navigation/native';
  43. import { useLoginState } from '../../context/loginContext';
  44. const styles = StyleSheet.create({
  45. container: {
  46. margin: 5,
  47. marginBottom: 20,
  48. },
  49. image: {
  50. width: 48,
  51. height: 48,
  52. },
  53. icon: {
  54. backgroundColor: 'transparent',
  55. },
  56. });
  57. function ServicesScreen() {
  58. const navigation = useNavigation();
  59. const theme = useTheme();
  60. const isLoggedIn = useLoginState();
  61. const finalDataset = getCategories(navigation.navigate, isLoggedIn, [
  62. SERVICES_CATEGORIES_KEY.SPECIAL,
  63. ]);
  64. useLayoutEffect(() => {
  65. const getAboutButton = () => (
  66. <MaterialHeaderButtons>
  67. <Item
  68. title="information"
  69. iconName="information"
  70. onPress={() => navigation.navigate('amicale-contact')}
  71. />
  72. </MaterialHeaderButtons>
  73. );
  74. navigation.setOptions({
  75. headerRight: getAboutButton,
  76. });
  77. }, [navigation]);
  78. /**
  79. * Gets the list title image for the list.
  80. *
  81. * If the source is a string, we are using an icon.
  82. * If the source is a number, we are using an internal image.
  83. *
  84. * @param source The source image to display. Can be a string for icons or a number for local images
  85. * @returns {*}
  86. */
  87. const getListTitleImage = (source: string | number) => {
  88. if (typeof source === 'number') {
  89. return <Image source={source} style={styles.image} />;
  90. }
  91. return (
  92. <Avatar.Icon
  93. size={48}
  94. icon={source}
  95. color={theme.colors.primary}
  96. style={styles.icon}
  97. />
  98. );
  99. };
  100. /**
  101. * A list item showing a list of available services for the current category
  102. *
  103. * @param item
  104. * @returns {*}
  105. */
  106. const getRenderItem = ({ item }: { item: ServiceCategoryType }) => {
  107. return (
  108. <TouchableRipple
  109. style={styles.container}
  110. onPress={() => navigation.navigate('services-section', { data: item })}
  111. >
  112. <View>
  113. <Card.Title
  114. title={item.title}
  115. subtitle={item.subtitle}
  116. left={() => getListTitleImage(item.image)}
  117. right={() => <List.Icon icon="chevron-right" />}
  118. />
  119. <CardList dataset={item.content} isHorizontal />
  120. </View>
  121. </TouchableRipple>
  122. );
  123. };
  124. const keyExtractor = (item: ServiceCategoryType): string => item.title;
  125. return (
  126. <View>
  127. <CollapsibleFlatList
  128. data={finalDataset}
  129. renderItem={getRenderItem}
  130. keyExtractor={keyExtractor}
  131. ItemSeparatorComponent={() => <Divider />}
  132. hasTab
  133. />
  134. <MascotPopup
  135. title={i18n.t('screens.services.mascotDialog.title')}
  136. message={i18n.t('screens.services.mascotDialog.message')}
  137. icon="cloud-question"
  138. buttons={{
  139. cancel: {
  140. message: i18n.t('screens.services.mascotDialog.button'),
  141. icon: 'check',
  142. },
  143. }}
  144. emotion={MASCOT_STYLE.WINK}
  145. />
  146. </View>
  147. );
  148. }
  149. export default ServicesScreen;