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.

PlanexBottomBar.tsx 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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, { useState } from 'react';
  20. import { StyleSheet, View, Animated } from 'react-native';
  21. import { FAB, IconButton, Surface, useTheme } from 'react-native-paper';
  22. import * as Animatable from 'react-native-animatable';
  23. import { TAB_BAR_HEIGHT } from '../Tabbar/CustomTabBar';
  24. import { useNavigation } from '@react-navigation/core';
  25. import { useCollapsible } from '../../context/CollapsibleContext';
  26. type Props = {
  27. onPress: (action: string, data?: string) => void;
  28. seekAttention: boolean;
  29. };
  30. const DISPLAY_MODES = {
  31. DAY: 'agendaDay',
  32. WEEK: 'agendaWeek',
  33. MONTH: 'month',
  34. };
  35. const styles = StyleSheet.create({
  36. container: {
  37. position: 'absolute',
  38. left: '5%',
  39. width: '90%',
  40. },
  41. surface: {
  42. position: 'relative',
  43. flexDirection: 'row',
  44. justifyContent: 'space-between',
  45. alignItems: 'center',
  46. borderRadius: 50,
  47. elevation: 2,
  48. },
  49. fabContainer: {
  50. position: 'absolute',
  51. left: 0,
  52. right: 0,
  53. alignItems: 'center',
  54. width: '100%',
  55. height: '100%',
  56. },
  57. fab: {
  58. position: 'absolute',
  59. alignSelf: 'center',
  60. top: '-25%',
  61. },
  62. side: {
  63. flexDirection: 'row',
  64. },
  65. icon: {
  66. marginLeft: 5,
  67. },
  68. });
  69. const DISPLAY_MODE_ICONS = {
  70. [DISPLAY_MODES.DAY]: 'calendar-text',
  71. [DISPLAY_MODES.WEEK]: 'calendar-week',
  72. [DISPLAY_MODES.MONTH]: 'calendar-range',
  73. };
  74. function PlanexBottomBar(props: Props) {
  75. const navigation = useNavigation();
  76. const theme = useTheme();
  77. const [currentMode, setCurrentMode] = useState(DISPLAY_MODES.WEEK);
  78. const { collapsible } = useCollapsible();
  79. const changeDisplayMode = () => {
  80. let newMode;
  81. switch (currentMode) {
  82. case DISPLAY_MODES.DAY:
  83. newMode = DISPLAY_MODES.WEEK;
  84. break;
  85. case DISPLAY_MODES.WEEK:
  86. newMode = DISPLAY_MODES.MONTH;
  87. break;
  88. case DISPLAY_MODES.MONTH:
  89. newMode = DISPLAY_MODES.DAY;
  90. break;
  91. default:
  92. newMode = DISPLAY_MODES.WEEK;
  93. break;
  94. }
  95. setCurrentMode(newMode);
  96. props.onPress('changeView', newMode);
  97. };
  98. let translateY: number | Animated.AnimatedInterpolation = 0;
  99. let opacity: number | Animated.AnimatedInterpolation = 1;
  100. let scale: number | Animated.AnimatedInterpolation = 1;
  101. if (collapsible) {
  102. translateY = Animated.multiply(-3, collapsible.translateY);
  103. opacity = Animated.subtract(1, collapsible.progress);
  104. scale = Animated.add(
  105. 0.5,
  106. Animated.multiply(0.5, Animated.subtract(1, collapsible.progress))
  107. );
  108. }
  109. const buttonColor = theme.colors.primary;
  110. return (
  111. <Animated.View
  112. style={{
  113. ...styles.container,
  114. bottom: 10 + TAB_BAR_HEIGHT,
  115. transform: [{ translateY: translateY }, { scale: scale }],
  116. opacity: opacity,
  117. }}
  118. >
  119. <Surface style={styles.surface}>
  120. <View style={styles.fabContainer}>
  121. <Animatable.View
  122. style={styles.fab}
  123. animation={props.seekAttention ? 'bounce' : undefined}
  124. easing={'ease-out'}
  125. iterationDelay={500}
  126. iterationCount={'infinite'}
  127. useNativeDriver={true}
  128. >
  129. <FAB
  130. icon={'account-clock'}
  131. onPress={() => navigation.navigate('group-select')}
  132. />
  133. </Animatable.View>
  134. </View>
  135. <View style={styles.side}>
  136. <IconButton
  137. icon={DISPLAY_MODE_ICONS[currentMode]}
  138. color={buttonColor}
  139. onPress={changeDisplayMode}
  140. />
  141. <IconButton
  142. icon="clock-in"
  143. color={buttonColor}
  144. style={styles.icon}
  145. onPress={() => props.onPress('today')}
  146. />
  147. </View>
  148. <View style={styles.side}>
  149. <IconButton
  150. icon="chevron-left"
  151. color={buttonColor}
  152. onPress={() => props.onPress('prev')}
  153. />
  154. <IconButton
  155. icon="chevron-right"
  156. color={buttonColor}
  157. style={styles.icon}
  158. onPress={() => props.onPress('next')}
  159. />
  160. </View>
  161. </Surface>
  162. </Animated.View>
  163. );
  164. }
  165. export default PlanexBottomBar;