Compare commits
No commits in common. "ac9709d6668a099bfe801d63ba943affd7f1967d" and "77cc5d87465a307b41d29da3d9a6a29244249b11" have entirely different histories.
ac9709d666
...
77cc5d8746
30 changed files with 839 additions and 839 deletions
6
App.js
6
App.js
|
|
@ -9,7 +9,7 @@ import {AppLoading} from 'expo';
|
|||
import type {CustomTheme} from "./src/managers/ThemeManager";
|
||||
import ThemeManager from './src/managers/ThemeManager';
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import MainNavigator from './src/navigation/MainNavigator';
|
||||
import DrawerNavigator from './src/navigation/DrawerNavigator';
|
||||
import {initExpoToken} from "./src/utils/Notifications";
|
||||
import {Provider as PaperProvider} from 'react-native-paper';
|
||||
import AprilFoolsManager from "./src/managers/AprilFoolsManager";
|
||||
|
|
@ -156,7 +156,7 @@ export default class App extends React.Component<Props, State> {
|
|||
*/
|
||||
onLoadFinished() {
|
||||
// Only show intro if this is the first time starting the app
|
||||
this.createDrawerNavigator = () => <MainNavigator
|
||||
this.createDrawerNavigator = () => <DrawerNavigator
|
||||
defaultHomeRoute={this.defaultHomeRoute}
|
||||
defaultHomeData={this.defaultHomeData}
|
||||
/>;
|
||||
|
|
@ -191,7 +191,7 @@ export default class App extends React.Component<Props, State> {
|
|||
return (
|
||||
<PaperProvider theme={this.state.currentTheme}>
|
||||
<NavigationContainer theme={this.state.currentTheme} ref={this.navigatorRef}>
|
||||
<MainNavigator
|
||||
<DrawerNavigator
|
||||
defaultHomeRoute={this.defaultHomeRoute}
|
||||
defaultHomeData={this.defaultHomeData}
|
||||
/>
|
||||
|
|
|
|||
BIN
assets/drawer-cover.png
Normal file
BIN
assets/drawer-cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
BIN
assets/proximo-logo.png
Normal file
BIN
assets/proximo-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
BIN
assets/proxiwash-logo.png
Normal file
BIN
assets/proxiwash-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 216 KiB |
|
|
@ -5,48 +5,36 @@ import {Avatar, Card, List, withTheme} from 'react-native-paper';
|
|||
import {StyleSheet} from "react-native";
|
||||
import {DrawerNavigationProp} from "@react-navigation/drawer";
|
||||
import type {CustomTheme} from "../../managers/ThemeManager";
|
||||
import i18n from 'i18n-js';
|
||||
|
||||
const ICON_AMICALE = require("../../../assets/amicale.png");
|
||||
|
||||
type Props = {
|
||||
navigation: DrawerNavigationProp,
|
||||
theme: CustomTheme,
|
||||
isLoggedIn: boolean,
|
||||
}
|
||||
|
||||
class ActionsDashBoardItem extends React.Component<Props> {
|
||||
|
||||
shouldComponentUpdate(nextProps: Props): boolean {
|
||||
return (nextProps.theme.dark !== this.props.theme.dark)
|
||||
|| (nextProps.isLoggedIn !== this.props.isLoggedIn);
|
||||
}
|
||||
|
||||
render() {
|
||||
const isLoggedIn = this.props.isLoggedIn;
|
||||
return (
|
||||
<Card style={{
|
||||
...styles.card,
|
||||
borderColor: this.props.theme.colors.primary,
|
||||
}}>
|
||||
<List.Item
|
||||
title={i18n.t("homeScreen.dashboard.amicaleTitle")}
|
||||
description={isLoggedIn
|
||||
? i18n.t("homeScreen.dashboard.amicaleConnected")
|
||||
: i18n.t("homeScreen.dashboard.amicaleConnect")}
|
||||
title={"AMICALE"}
|
||||
description={"VOTRE COMPTE"}
|
||||
left={props => <Avatar.Image
|
||||
{...props}
|
||||
size={40}
|
||||
source={ICON_AMICALE}
|
||||
style={styles.avatar}/>}
|
||||
right={props => <List.Icon {...props} icon={isLoggedIn
|
||||
? "chevron-right"
|
||||
: "login"}/>}
|
||||
onPress={isLoggedIn
|
||||
? () => this.props.navigation.navigate("services", {
|
||||
screen: 'index'
|
||||
})
|
||||
: () => this.props.navigation.navigate("login")}
|
||||
right={props => <List.Icon {...props} icon="chevron-right"/>}
|
||||
onPress={() => this.props.navigation.navigate("amicale-home")}
|
||||
style={styles.list}
|
||||
/>
|
||||
</Card>
|
||||
|
|
@ -63,14 +51,12 @@ const styles = StyleSheet.create({
|
|||
borderWidth: 1,
|
||||
},
|
||||
avatar: {
|
||||
backgroundColor: 'transparent',
|
||||
marginTop: 'auto',
|
||||
marginBottom: 'auto',
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
list: {
|
||||
// height: 50,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingTop:0,
|
||||
paddingBottom:0,
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type Props = {
|
|||
};
|
||||
|
||||
const AnimatableBadge = Animatable.createAnimatableComponent(Badge);
|
||||
const AnimatableIconButton = Animatable.createAnimatableComponent(IconButton);
|
||||
|
||||
/**
|
||||
* Component used to render a small dashboard item
|
||||
|
|
@ -33,7 +34,7 @@ class SmallDashboardItem extends React.Component<Props> {
|
|||
const colors = props.theme.colors;
|
||||
return (
|
||||
<View>
|
||||
<IconButton
|
||||
<AnimatableIconButton
|
||||
icon={props.icon}
|
||||
color={
|
||||
props.isAvailable
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Animated} from "react-native";
|
||||
import ImageListItem from "./ImageListItem";
|
||||
import CardListItem from "./CardListItem";
|
||||
|
||||
type Props = {
|
||||
dataset: Array<cardItem>,
|
||||
isHorizontal: boolean,
|
||||
}
|
||||
|
||||
export type cardItem = {
|
||||
title: string,
|
||||
subtitle: string,
|
||||
image: string | number,
|
||||
onPress: () => void,
|
||||
};
|
||||
|
||||
export type cardList = Array<cardItem>;
|
||||
|
||||
|
||||
export default class CardList extends React.Component<Props> {
|
||||
|
||||
static defaultProps = {
|
||||
isHorizontal: false,
|
||||
}
|
||||
|
||||
renderItem = ({item}: { item: cardItem }) => {
|
||||
if (this.props.isHorizontal)
|
||||
return <ImageListItem item={item} key={item.title}/>;
|
||||
else
|
||||
return <CardListItem item={item} key={item.title}/>;
|
||||
};
|
||||
|
||||
keyExtractor = (item: cardItem) => item.title;
|
||||
|
||||
render() {
|
||||
let containerStyle;
|
||||
if (this.props.isHorizontal) {
|
||||
containerStyle = {
|
||||
...this.props.contentContainerStyle,
|
||||
height: 150,
|
||||
justifyContent: 'space-around',
|
||||
};
|
||||
} else {
|
||||
containerStyle = {
|
||||
...this.props.contentContainerStyle,
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Animated.FlatList
|
||||
{...this.props}
|
||||
data={this.props.dataset}
|
||||
renderItem={this.renderItem}
|
||||
keyExtractor={this.keyExtractor}
|
||||
numColumns={this.props.isHorizontal ? undefined : 2}
|
||||
horizontal={this.props.isHorizontal}
|
||||
contentContainerStyle={containerStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Caption, Card, Paragraph} from 'react-native-paper';
|
||||
import type {cardItem} from "./CardList";
|
||||
|
||||
type Props = {
|
||||
item: cardItem,
|
||||
}
|
||||
|
||||
export default class CardListItem extends React.Component<Props> {
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const item = props.item;
|
||||
const source = typeof item.image === "number"
|
||||
? item.image
|
||||
: {uri: item.image};
|
||||
return (
|
||||
<Card
|
||||
style={{
|
||||
width: '40%',
|
||||
margin: 5,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
}}
|
||||
onPress={item.onPress}
|
||||
>
|
||||
<Card.Cover
|
||||
style={{height: 80}}
|
||||
source={source}
|
||||
/>
|
||||
<Card.Content>
|
||||
<Paragraph>{item.title}</Paragraph>
|
||||
<Caption>{item.subtitle}</Caption>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Text, TouchableRipple} from 'react-native-paper';
|
||||
import {Image, View} from 'react-native';
|
||||
import type {cardItem} from "./CardList";
|
||||
|
||||
type Props = {
|
||||
item: cardItem,
|
||||
}
|
||||
|
||||
export default class ImageListItem extends React.Component<Props> {
|
||||
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const item = props.item;
|
||||
const source = typeof item.image === "number"
|
||||
? item.image
|
||||
: {uri: item.image};
|
||||
return (
|
||||
<TouchableRipple
|
||||
style={{
|
||||
width: 100,
|
||||
height: 150,
|
||||
margin: 5,
|
||||
}}
|
||||
onPress={item.onPress}
|
||||
>
|
||||
<View>
|
||||
<Image
|
||||
style={{
|
||||
width: 80,
|
||||
height: 80,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
}}
|
||||
source={source}
|
||||
/>
|
||||
<Text style={{
|
||||
marginTop: 5,
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
textAlign: 'center'
|
||||
}}>{item.title}</Text>
|
||||
</View>
|
||||
</TouchableRipple>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,13 +6,15 @@ import {HeaderButton, HeaderButtons} from 'react-navigation-header-buttons';
|
|||
import {withTheme} from "react-native-paper";
|
||||
import * as Touchable from "react-native/Libraries/Components/Touchable/TouchableNativeFeedback.android";
|
||||
|
||||
const MaterialHeaderButton = (props: Object) => <HeaderButton
|
||||
const MaterialHeaderButton = (props: Object) => (
|
||||
<HeaderButton
|
||||
IconComponent={MaterialCommunityIcons}
|
||||
iconSize={26}
|
||||
color={props.color != null ? props.color : props.theme.colors.text}
|
||||
color={props.theme.colors.text}
|
||||
background={Touchable.Ripple(props.theme.colors.ripple, true)}
|
||||
{...props}
|
||||
/>;
|
||||
/>
|
||||
);
|
||||
|
||||
const MaterialHeaderButtons = (props: Object) => {
|
||||
return (
|
||||
|
|
|
|||
148
src/components/Sidebar/SideBarSection.js
Normal file
148
src/components/Sidebar/SideBarSection.js
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {FlatList} from "react-native";
|
||||
import {Drawer, withTheme} from 'react-native-paper';
|
||||
import {Linking} from "expo";
|
||||
import AnimatedAccordion from "../Animations/AnimatedAccordion";
|
||||
import {StackActions} from '@react-navigation/native';
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
startOpen: boolean,
|
||||
isLoggedIn: boolean,
|
||||
sectionName: string,
|
||||
activeRoute: string,
|
||||
listKey: string,
|
||||
listData: Array<Object>,
|
||||
}
|
||||
|
||||
const LIST_ITEM_HEIGHT = 48;
|
||||
|
||||
class SideBarSection extends React.PureComponent<Props> {
|
||||
|
||||
colors: Object;
|
||||
accordionRef: {current: null | AnimatedAccordion};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
this.accordionRef = React.createRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches if the current route is contained in the given list data.
|
||||
* If this is the case and the list is collapsed, we should expand this list.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
shouldExpandList() {
|
||||
for (let i = 0; i < this.props.listData.length; i++) {
|
||||
if (this.props.listData[i].route === this.props.activeRoute) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback when a drawer item is pressed.
|
||||
* It will either navigate to the associated screen, or open the browser to the associated link
|
||||
*
|
||||
* @param item The item pressed
|
||||
*/
|
||||
onListItemPress(item: Object) {
|
||||
if (item.link !== undefined)
|
||||
Linking.openURL(item.link);
|
||||
else if (item.action !== undefined)
|
||||
item.action();
|
||||
else if (this.props.activeRoute === "main")
|
||||
this.props.navigation.navigate(item.route);
|
||||
else {
|
||||
this.props.navigation.dispatch(
|
||||
StackActions.replace(item.route)
|
||||
);
|
||||
this.props.navigation.closeDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key extractor for list items
|
||||
*
|
||||
* @param item The item to extract the key from
|
||||
* @return {string} The extracted key
|
||||
*/
|
||||
listKeyExtractor = (item: Object) => item.route;
|
||||
|
||||
shouldHideItem(item: Object) {
|
||||
const onlyWhenLoggedOut = item.onlyWhenLoggedOut !== undefined && item.onlyWhenLoggedOut === true;
|
||||
const onlyWhenLoggedIn = item.onlyWhenLoggedIn !== undefined && item.onlyWhenLoggedIn === true;
|
||||
return (onlyWhenLoggedIn && !this.props.isLoggedIn || onlyWhenLoggedOut && this.props.isLoggedIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the render item for the given list item
|
||||
*
|
||||
* @param item The item to render
|
||||
* @return {*}
|
||||
*/
|
||||
getRenderItem = ({item}: Object) => {
|
||||
const onListItemPress = this.onListItemPress.bind(this, item);
|
||||
if (this.shouldHideItem(item))
|
||||
return null;
|
||||
return (
|
||||
<Drawer.Item
|
||||
label={item.name}
|
||||
active={this.props.activeRoute === item.route}
|
||||
icon={item.icon}
|
||||
onPress={onListItemPress}
|
||||
style={{
|
||||
height: LIST_ITEM_HEIGHT,
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
shouldRenderAccordion() {
|
||||
let itemsToRender = 0;
|
||||
for (let i = 0; i < this.props.listData.length; i++) {
|
||||
if (!this.shouldHideItem(this.props.listData[i]))
|
||||
itemsToRender += 1;
|
||||
}
|
||||
return itemsToRender > 1;
|
||||
}
|
||||
|
||||
itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
|
||||
|
||||
getFlatList() {
|
||||
return (
|
||||
// $FlowFixMe
|
||||
<FlatList
|
||||
data={this.props.listData}
|
||||
extraData={this.props.isLoggedIn.toString() + this.props.activeRoute}
|
||||
renderItem={this.getRenderItem}
|
||||
keyExtractor={this.listKeyExtractor}
|
||||
listKey={this.props.listKey}
|
||||
// Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
|
||||
getItemLayout={this.itemLayout}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.shouldRenderAccordion()) {
|
||||
return (
|
||||
<AnimatedAccordion
|
||||
title={this.props.sectionName}
|
||||
keepOpen={this.shouldExpandList()}
|
||||
>
|
||||
{this.getFlatList()}
|
||||
</AnimatedAccordion>
|
||||
);
|
||||
} else
|
||||
return this.getFlatList();
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(SideBarSection);
|
||||
267
src/components/Sidebar/Sidebar.js
Normal file
267
src/components/Sidebar/Sidebar.js
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Dimensions, FlatList, Image, StyleSheet, View,} from 'react-native';
|
||||
import i18n from "i18n-js";
|
||||
import {TouchableRipple} from "react-native-paper";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import LogoutDialog from "../Amicale/LogoutDialog";
|
||||
import SideBarSection from "./SideBarSection";
|
||||
import {DrawerNavigationProp} from "@react-navigation/drawer";
|
||||
|
||||
const deviceWidth = Dimensions.get("window").width;
|
||||
|
||||
type Props = {
|
||||
navigation: DrawerNavigationProp,
|
||||
state: {[key: string] : any},
|
||||
theme?: Object,
|
||||
};
|
||||
|
||||
type State = {
|
||||
isLoggedIn: boolean,
|
||||
dialogVisible: boolean,
|
||||
};
|
||||
|
||||
/**
|
||||
* Component used to render the drawer menu content
|
||||
*/
|
||||
class SideBar extends React.Component<Props, State> {
|
||||
|
||||
dataSet: Array<Object>;
|
||||
activeRoute: string;
|
||||
/**
|
||||
* Generate the dataset
|
||||
*
|
||||
* @param props
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.activeRoute = 'main';
|
||||
// Dataset used to render the drawer
|
||||
const mainData = [
|
||||
{
|
||||
name: i18n.t('screens.home'),
|
||||
route: "main",
|
||||
icon: "home",
|
||||
},
|
||||
];
|
||||
const amicaleData = [
|
||||
{
|
||||
name: i18n.t('screens.login'),
|
||||
route: "login",
|
||||
icon: "login",
|
||||
onlyWhenLoggedOut: true,
|
||||
shouldEmphasis: true,
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.amicaleAbout'),
|
||||
route: "amicale-contact",
|
||||
icon: "information",
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.profile'),
|
||||
route: "profile",
|
||||
icon: "account",
|
||||
onlyWhenLoggedIn: true,
|
||||
},
|
||||
{
|
||||
name: i18n.t('clubs.clubList'),
|
||||
route: "club-list",
|
||||
icon: "account-group",
|
||||
onlyWhenLoggedIn: true,
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.vote'),
|
||||
route: "vote",
|
||||
icon: "vote",
|
||||
onlyWhenLoggedIn: true,
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.logout'),
|
||||
route: 'disconnect',
|
||||
action: this.showDisconnectDialog,
|
||||
icon: "logout",
|
||||
onlyWhenLoggedIn: true,
|
||||
},
|
||||
];
|
||||
const servicesData = [
|
||||
{
|
||||
name: i18n.t('screens.menuSelf'),
|
||||
route: "self-menu",
|
||||
icon: "silverware-fork-knife",
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.availableRooms'),
|
||||
route: "available-rooms",
|
||||
icon: "calendar-check",
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.bib'),
|
||||
route: "bib",
|
||||
icon: "book",
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.bluemind'),
|
||||
route: "bluemind",
|
||||
link: "https://etud-mel.insa-toulouse.fr/webmail/",
|
||||
icon: "email",
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.ent'),
|
||||
route: "ent",
|
||||
link: "https://ent.insa-toulouse.fr/",
|
||||
icon: "notebook",
|
||||
},
|
||||
];
|
||||
const websitesData = [
|
||||
{
|
||||
name: "Amicale",
|
||||
route: "amicale-website",
|
||||
icon: "alpha-a-box",
|
||||
},
|
||||
{
|
||||
name: "Élus Étudiants",
|
||||
route: "elus-etudiants",
|
||||
icon: "alpha-e-box",
|
||||
},
|
||||
{
|
||||
name: "Wiketud",
|
||||
route: "wiketud",
|
||||
icon: "wikipedia",
|
||||
},
|
||||
{
|
||||
name: "Tutor'INSA",
|
||||
route: "tutorinsa",
|
||||
icon: "school",
|
||||
},
|
||||
];
|
||||
const othersData = [
|
||||
{
|
||||
name: i18n.t('screens.settings'),
|
||||
route: "settings",
|
||||
icon: "settings",
|
||||
},
|
||||
{
|
||||
name: i18n.t('screens.about'),
|
||||
route: "about",
|
||||
icon: "information",
|
||||
},
|
||||
];
|
||||
|
||||
this.dataSet = [
|
||||
{
|
||||
key: '1',
|
||||
name: i18n.t('screens.home'),
|
||||
startOpen: true, // App always starts on Main
|
||||
data: mainData
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: i18n.t('sidenav.divider4'),
|
||||
startOpen: false, // TODO set by user preferences
|
||||
data: amicaleData
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
name: i18n.t('sidenav.divider2'),
|
||||
startOpen: false,
|
||||
data: servicesData
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
name: i18n.t('sidenav.divider1'),
|
||||
startOpen: false,
|
||||
data: websitesData
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
name: i18n.t('sidenav.divider3'),
|
||||
startOpen: false,
|
||||
data: othersData
|
||||
},
|
||||
];
|
||||
ConnectionManager.getInstance().addLoginStateListener(this.onLoginStateChange);
|
||||
this.state = {
|
||||
isLoggedIn: ConnectionManager.getInstance().isLoggedIn(),
|
||||
dialogVisible: false,
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
|
||||
const nextNavigationState = nextProps.state.routes[0].state;
|
||||
const nextRoute = nextNavigationState.routes[nextNavigationState.index].name;
|
||||
|
||||
let currentRoute = "main";
|
||||
const currentNavigationState = this.props.state.routes[0].state;
|
||||
if (currentNavigationState != null) {
|
||||
currentRoute = currentNavigationState.routes[currentNavigationState.index].name;
|
||||
}
|
||||
|
||||
|
||||
this.activeRoute = nextRoute;
|
||||
return (nextState !== this.state)
|
||||
|| (nextRoute !== currentRoute);
|
||||
}
|
||||
|
||||
showDisconnectDialog = () => this.setState({dialogVisible: true});
|
||||
|
||||
hideDisconnectDialog = () => this.setState({dialogVisible: false});
|
||||
|
||||
onLoginStateChange = (isLoggedIn: boolean) => this.setState({isLoggedIn: isLoggedIn});
|
||||
|
||||
/**
|
||||
* Gets the render item for the given list item
|
||||
*
|
||||
* @param item The item to render
|
||||
* @return {*}
|
||||
*/
|
||||
getRenderItem = ({item}: Object) => {
|
||||
return <SideBarSection
|
||||
{...this.props}
|
||||
listKey={item.key}
|
||||
activeRoute={this.activeRoute}
|
||||
isLoggedIn={this.state.isLoggedIn}
|
||||
sectionName={item.name}
|
||||
startOpen={item.startOpen}
|
||||
listData={item.data}
|
||||
/>
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={{height: '100%'}}>
|
||||
<TouchableRipple
|
||||
onPress={() => this.props.navigation.navigate("tetris")}
|
||||
>
|
||||
<Image
|
||||
source={require("../../../assets/drawer-cover.png")}
|
||||
style={styles.drawerCover}
|
||||
/>
|
||||
</TouchableRipple>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
data={this.dataSet}
|
||||
extraData={this.state.isLoggedIn.toString() + this.activeRoute}
|
||||
renderItem={this.getRenderItem}
|
||||
/>
|
||||
<LogoutDialog
|
||||
{...this.props}
|
||||
visible={this.state.dialogVisible}
|
||||
onDismiss={this.hideDisconnectDialog}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
drawerCover: {
|
||||
height: deviceWidth / 3,
|
||||
width: 2 * deviceWidth / 3,
|
||||
position: "relative",
|
||||
marginBottom: 10,
|
||||
marginTop: 20
|
||||
},
|
||||
});
|
||||
|
||||
export default SideBar;
|
||||
|
|
@ -19,8 +19,8 @@ type State = {
|
|||
|
||||
const TAB_ICONS = {
|
||||
proxiwash: 'tshirt-crew',
|
||||
services: 'account-circle',
|
||||
planning: 'calendar-range',
|
||||
students: 'account-circle',
|
||||
insa: 'book',
|
||||
planex: 'clock',
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
|
|||
import DebugScreen from '../screens/About/DebugScreen';
|
||||
import {createStackNavigator, TransitionPresets} from "@react-navigation/stack";
|
||||
import i18n from "i18n-js";
|
||||
import TabNavigator from "./TabNavigator";
|
||||
import TetrisScreen from "../screens/Tetris/TetrisScreen";
|
||||
import TabNavigator from "./MainTabNavigator";
|
||||
|
||||
const defaultScreenOptions = {
|
||||
gestureEnabled: true,
|
||||
|
|
@ -60,13 +59,6 @@ function MainStackComponent(props: { createTabNavigator: () => React.Node }) {
|
|||
title: i18n.t('aboutScreen.debug')
|
||||
}}
|
||||
/>
|
||||
<MainStack.Screen
|
||||
name="tetris"
|
||||
component={TetrisScreen}
|
||||
options={{
|
||||
title: i18n.t("game.title"),
|
||||
}}
|
||||
/>
|
||||
</MainStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
|
@ -76,7 +68,7 @@ type Props = {
|
|||
defaultHomeData: { [key: string]: any }
|
||||
}
|
||||
|
||||
export default class MainNavigator extends React.Component<Props> {
|
||||
export default class DrawerNavigator extends React.Component<Props> {
|
||||
|
||||
createTabNavigator: () => React.Node;
|
||||
|
||||
|
|
@ -21,23 +21,23 @@ import FeedItemScreen from "../screens/Home/FeedItemScreen";
|
|||
import {createCollapsibleStack} from "react-navigation-collapsible";
|
||||
import GroupSelectionScreen from "../screens/Planex/GroupSelectionScreen";
|
||||
import CustomTabBar from "../components/Tabbar/CustomTabBar";
|
||||
import SelfMenuScreen from "../screens/Services/SelfMenuScreen";
|
||||
import SelfMenuScreen from "../screens/Other/SelfMenuScreen";
|
||||
import AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen";
|
||||
import BibScreen from "../screens/Websites/BibScreen";
|
||||
import {AmicaleWebsiteScreen} from "../screens/Websites/AmicaleWebsiteScreen";
|
||||
import {ElusEtudiantsWebsiteScreen} from "../screens/Websites/ElusEtudiantsWebsiteScreen";
|
||||
import {WiketudWebsiteScreen} from "../screens/Websites/WiketudWebsiteScreen";
|
||||
import {TutorInsaWebsiteScreen} from "../screens/Websites/TutorInsaWebsiteScreen";
|
||||
import {ENTWebsiteScreen} from "../screens/Websites/ENTWebsiteScreen";
|
||||
import {BlueMindWebsiteScreen} from "../screens/Websites/BlueMindWebsiteScreen";
|
||||
import TetrisScreen from "../screens/Tetris/TetrisScreen";
|
||||
import LoginScreen from "../screens/Amicale/LoginScreen";
|
||||
import ProfileScreen from "../screens/Amicale/ProfileScreen";
|
||||
import ClubListScreen from "../screens/Amicale/Clubs/ClubListScreen";
|
||||
import ClubAboutScreen from "../screens/Amicale/Clubs/ClubAboutScreen";
|
||||
import VoteScreen from "../screens/Amicale/VoteScreen";
|
||||
import AmicaleContactScreen from "../screens/Amicale/AmicaleContactScreen";
|
||||
import WebsitesHomeScreen from "../screens/Services/ServicesScreen";
|
||||
import ServicesSectionScreen from "../screens/Services/ServicesSectionScreen";
|
||||
import AmicaleHomeScreen from "../screens/Amicale/AmicaleHomeScreen";
|
||||
import WebsitesHomeScreen from "../screens/Websites/WebsitesHomeScreen";
|
||||
import InsaHomeScreen from "../screens/Insa/InsaHomeScreen";
|
||||
|
||||
const defaultScreenOptions = {
|
||||
gestureEnabled: true,
|
||||
|
|
@ -77,39 +77,41 @@ function createScreenCollapsibleStack(
|
|||
)
|
||||
}
|
||||
|
||||
function getWebsiteStack(name: string, Stack: any, component: any, title: string) {
|
||||
function getWebsiteStack(name: string, Stack: any, component: any, title: string) {
|
||||
return createScreenCollapsibleStack(name, Stack, component, title, false);
|
||||
}
|
||||
|
||||
|
||||
const ServicesStack = createStackNavigator();
|
||||
const StudentsStack = createStackNavigator();
|
||||
|
||||
function ServicesStackComponent() {
|
||||
function StudentsStackComponent() {
|
||||
return (
|
||||
<ServicesStack.Navigator
|
||||
<StudentsStack.Navigator
|
||||
initialRouteName="index"
|
||||
headerMode={"screen"}
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
{createScreenCollapsibleStack("index", ServicesStack, WebsitesHomeScreen, i18n.t('screens.services'))}
|
||||
{createScreenCollapsibleStack("services-section", ServicesStack, ServicesSectionScreen, "SECTION")}
|
||||
|
||||
{/* INSA */}
|
||||
{getWebsiteStack("available-rooms", ServicesStack, AvailableRoomScreen, i18n.t('screens.availableRooms'))}
|
||||
{getWebsiteStack("bib", ServicesStack, BibScreen, i18n.t('screens.bib'))}
|
||||
{createScreenCollapsibleStack("self-menu", ServicesStack, SelfMenuScreen, i18n.t('screens.menuSelf'))}
|
||||
|
||||
{/* STUDENTS */}
|
||||
{createScreenCollapsibleStack("proximo", ServicesStack, ProximoMainScreen, i18n.t('screens.proximo'))}
|
||||
<StudentsStack.Screen
|
||||
name="index"
|
||||
component={WebsitesHomeScreen}
|
||||
options={{
|
||||
title: "WEBSITES HOME",
|
||||
}}
|
||||
/>
|
||||
{getWebsiteStack("amicale-website", StudentsStack, AmicaleWebsiteScreen, "Amicale")}
|
||||
{getWebsiteStack("elus-etudiants", StudentsStack, ElusEtudiantsWebsiteScreen, "Élus Étudiants")}
|
||||
{getWebsiteStack("wiketud", StudentsStack, WiketudWebsiteScreen, "Wiketud")}
|
||||
{getWebsiteStack("tutorinsa", StudentsStack, TutorInsaWebsiteScreen, "Tutor'INSA")}
|
||||
{createScreenCollapsibleStack("proximo", StudentsStack, ProximoMainScreen, "Proximo")}
|
||||
{createScreenCollapsibleStack(
|
||||
"proximo-list",
|
||||
ServicesStack,
|
||||
StudentsStack,
|
||||
ProximoListScreen,
|
||||
i18n.t('screens.proximoArticles'),
|
||||
true,
|
||||
{...screenTransition},
|
||||
)}
|
||||
<ServicesStack.Screen
|
||||
<StudentsStack.Screen
|
||||
name="proximo-about"
|
||||
component={ProximoAboutScreen}
|
||||
options={{
|
||||
|
|
@ -117,41 +119,22 @@ function ServicesStackComponent() {
|
|||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
{getWebsiteStack("amicale-website", ServicesStack, AmicaleWebsiteScreen, i18n.t('screens.amicaleWebsite'))}
|
||||
{getWebsiteStack("elus-etudiants", ServicesStack, ElusEtudiantsWebsiteScreen, "Élus Étudiants")}
|
||||
{getWebsiteStack("wiketud", ServicesStack, WiketudWebsiteScreen, "Wiketud")}
|
||||
{getWebsiteStack("tutorinsa", ServicesStack, TutorInsaWebsiteScreen, "Tutor'INSA")}
|
||||
{getWebsiteStack("ent", ServicesStack, ENTWebsiteScreen, i18n.t('screens.ent'))}
|
||||
{getWebsiteStack("bluemind", ServicesStack, BlueMindWebsiteScreen, i18n.t('screens.bluemind'))}
|
||||
|
||||
|
||||
{/* AMICALE */}
|
||||
{createScreenCollapsibleStack("login", ServicesStack, LoginScreen, i18n.t('screens.login'))}
|
||||
{createScreenCollapsibleStack("profile", ServicesStack, ProfileScreen, i18n.t('screens.profile'))}
|
||||
{createScreenCollapsibleStack("club-list", ServicesStack, ClubListScreen, i18n.t('clubs.clubList'))}
|
||||
<ServicesStack.Screen
|
||||
name="club-about"
|
||||
component={ClubAboutScreen}
|
||||
<StudentsStack.Screen
|
||||
name="planning"
|
||||
component={PlanningScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.clubsAbout'),
|
||||
title: i18n.t('screens.planning'),
|
||||
}}
|
||||
/>
|
||||
<StudentsStack.Screen
|
||||
name="planning-information"
|
||||
component={PlanningDisplayScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.planningDisplayScreen'),
|
||||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
<ServicesStack.Screen
|
||||
name="vote"
|
||||
component={VoteScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.vote'),
|
||||
}}
|
||||
/>
|
||||
<ServicesStack.Screen
|
||||
name="amicale-contact"
|
||||
component={AmicaleContactScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.amicaleAbout'),
|
||||
}}
|
||||
/>
|
||||
</ServicesStack.Navigator>
|
||||
</StudentsStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -177,31 +160,26 @@ function ProxiwashStackComponent() {
|
|||
);
|
||||
}
|
||||
|
||||
const PlanningStack = createStackNavigator();
|
||||
const InsaStack = createStackNavigator();
|
||||
|
||||
function PlanningStackComponent() {
|
||||
function InsaStackComponent() {
|
||||
return (
|
||||
<PlanningStack.Navigator
|
||||
<InsaStack.Navigator
|
||||
initialRouteName="index"
|
||||
headerMode={"screen"}
|
||||
screenOptions={defaultScreenOptions}
|
||||
>
|
||||
<PlanningStack.Screen
|
||||
name="planning"
|
||||
component={PlanningScreen}
|
||||
<InsaStack.Screen
|
||||
name="index"
|
||||
component={InsaHomeScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.planning'),
|
||||
title: "INSA HOME",
|
||||
}}
|
||||
/>
|
||||
<PlanningStack.Screen
|
||||
name="planning-information"
|
||||
component={PlanningDisplayScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.planningDisplayScreen'),
|
||||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
</PlanningStack.Navigator>
|
||||
{getWebsiteStack("available-rooms", InsaStack, AvailableRoomScreen, i18n.t('screens.availableRooms'))}
|
||||
{getWebsiteStack("bib", InsaStack, BibScreen, i18n.t('screens.bib'))}
|
||||
{createScreenCollapsibleStack("self-menu", InsaStack, SelfMenuScreen, i18n.t('screens.menuSelf'))}
|
||||
</InsaStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -235,6 +213,14 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
|
|||
useNativeDriver: true,
|
||||
}
|
||||
)}
|
||||
<HomeStack.Screen
|
||||
name="feed-information"
|
||||
component={FeedItemScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.feedDisplayScreen'),
|
||||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="scanner"
|
||||
component={ScannerScreen}
|
||||
|
|
@ -243,6 +229,36 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
|
|||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="home-planning-information"
|
||||
component={PlanningDisplayScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.planningDisplayScreen'),
|
||||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="tetris"
|
||||
component={TetrisScreen}
|
||||
options={{
|
||||
title: i18n.t("game.title"),
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="login"
|
||||
component={LoginScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.login'),
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="profile"
|
||||
component={ProfileScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.profile'),
|
||||
}}
|
||||
/>
|
||||
{createScreenCollapsibleStack("club-list", HomeStack, ClubListScreen, i18n.t('clubs.clubList'))}
|
||||
<HomeStack.Screen
|
||||
name="club-information"
|
||||
component={ClubDisplayScreen}
|
||||
|
|
@ -252,23 +268,34 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
|
|||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="feed-information"
|
||||
component={FeedItemScreen}
|
||||
name="club-about"
|
||||
component={ClubAboutScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.feedDisplayScreen'),
|
||||
title: i18n.t('screens.clubsAbout'),
|
||||
...modalTransition,
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="planning-information"
|
||||
component={PlanningDisplayScreen}
|
||||
name="vote"
|
||||
component={VoteScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.planningDisplayScreen'),
|
||||
...modalTransition,
|
||||
title: i18n.t('screens.vote'),
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="amicale-contact"
|
||||
component={AmicaleContactScreen}
|
||||
options={{
|
||||
title: i18n.t('screens.amicaleAbout'),
|
||||
}}
|
||||
/>
|
||||
<HomeStack.Screen
|
||||
name="amicale-home"
|
||||
component={AmicaleHomeScreen}
|
||||
options={{
|
||||
title: "AMICALE HOME",
|
||||
}}
|
||||
/>
|
||||
{createScreenCollapsibleStack("self-menu", HomeStack, SelfMenuScreen, i18n.t('screens.menuSelf'), true, {...modalTransition})}
|
||||
{createScreenCollapsibleStack("login", HomeStack, LoginScreen, i18n.t('screens.login'))}
|
||||
</HomeStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
|
@ -321,26 +348,27 @@ export default class TabNavigator extends React.Component<Props> {
|
|||
initialRouteName={this.defaultRoute}
|
||||
tabBar={props => <CustomTabBar {...props} />}
|
||||
>
|
||||
<Tab.Screen
|
||||
name="services"
|
||||
option
|
||||
component={ServicesStackComponent}
|
||||
options={{title: i18n.t('screens.services')}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="proxiwash"
|
||||
component={ProxiwashStackComponent}
|
||||
options={{title: i18n.t('screens.proxiwash')}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="students"
|
||||
option
|
||||
component={StudentsStackComponent}
|
||||
options={{title: "ETUDIANTS"}}
|
||||
/>
|
||||
|
||||
<Tab.Screen
|
||||
name="home"
|
||||
component={this.createHomeStackComponent}
|
||||
options={{title: i18n.t('screens.home')}}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="planning"
|
||||
component={PlanningStackComponent}
|
||||
options={{title: i18n.t('screens.planning')}}
|
||||
name="insa"
|
||||
component={InsaStackComponent}
|
||||
options={{title: "INSA"}}
|
||||
/>
|
||||
|
||||
<Tab.Screen
|
||||
|
|
@ -1,21 +1,16 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Animated, KeyboardAvoidingView, StyleSheet, View} from "react-native";
|
||||
import {KeyboardAvoidingView, ScrollView, StyleSheet, View} from "react-native";
|
||||
import {Avatar, Button, Card, HelperText, Paragraph, TextInput, withTheme} from 'react-native-paper';
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import i18n from 'i18n-js';
|
||||
import ErrorDialog from "../../components/Dialogs/ErrorDialog";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
import {Collapsible} from "react-navigation-collapsible";
|
||||
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
|
||||
import type {CustomTheme} from "../../managers/ThemeManager";
|
||||
import {CommonActions} from "@react-navigation/native";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
route: Object,
|
||||
collapsibleStack: Collapsible,
|
||||
theme: CustomTheme
|
||||
}
|
||||
|
||||
type State = {
|
||||
|
|
@ -46,17 +41,32 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
dialogError: 0,
|
||||
};
|
||||
|
||||
colors: Object;
|
||||
|
||||
onEmailChange: Function;
|
||||
onPasswordChange: Function;
|
||||
passwordInputRef: Object;
|
||||
|
||||
nextScreen: string;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onEmailChange = this.onInputChange.bind(this, true);
|
||||
this.onPasswordChange = this.onInputChange.bind(this, false);
|
||||
|
||||
this.colors = props.theme.colors;
|
||||
|
||||
this.props.navigation.addListener('focus', this.onScreenFocus);
|
||||
}
|
||||
|
||||
onScreenFocus = () => {
|
||||
if (this.props.route.params !== undefined && this.props.route.params.nextScreen !== undefined) {
|
||||
this.nextScreen = this.props.route.params.nextScreen;
|
||||
this.props.navigation.dispatch(CommonActions.setParams({nextScreen: 'profile'}));
|
||||
} else
|
||||
this.nextScreen = 'profile';
|
||||
};
|
||||
|
||||
showErrorDialog = (error: number) =>
|
||||
this.setState({
|
||||
dialogVisible: true,
|
||||
|
|
@ -65,7 +75,7 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
|
||||
hideErrorDialog = () => this.setState({dialogVisible: false});
|
||||
|
||||
handleSuccess = () => this.props.navigation.goBack();
|
||||
handleSuccess = () => this.props.navigation.replace(this.nextScreen);
|
||||
|
||||
onResetPasswordClick = () => this.props.navigation.navigate('amicale-website', {
|
||||
screen: 'amicale-website',
|
||||
|
|
@ -225,7 +235,7 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
left={(props) => <Avatar.Icon
|
||||
{...props}
|
||||
icon={"help"}
|
||||
color={this.props.theme.colors.primary}
|
||||
color={this.colors.primary}
|
||||
style={{backgroundColor: 'transparent'}}/>}
|
||||
/>
|
||||
<Card.Content>
|
||||
|
|
@ -238,7 +248,6 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
behavior={"height"}
|
||||
|
|
@ -247,14 +256,7 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
enabled
|
||||
keyboardVerticalOffset={100}
|
||||
>
|
||||
<Animated.ScrollView
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{
|
||||
paddingTop: containerPaddingTop,
|
||||
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
|
||||
}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
>
|
||||
<ScrollView>
|
||||
<View>
|
||||
{this.getMainCard()}
|
||||
{this.getSecondaryCard()}
|
||||
|
|
@ -264,7 +266,7 @@ class LoginScreen extends React.Component<Props, State> {
|
|||
onDismiss={this.hideErrorDialog}
|
||||
errorCode={this.state.dialogError}
|
||||
/>
|
||||
</Animated.ScrollView>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
}
|
||||
|
|
@ -290,4 +292,4 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
export default withCollapsible(withTheme(LoginScreen));
|
||||
export default withTheme(LoginScreen);
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {Animated, FlatList, StyleSheet, View} from "react-native";
|
||||
import {FlatList, StyleSheet, View} from "react-native";
|
||||
import {Avatar, Button, Card, Divider, List, withTheme} from 'react-native-paper';
|
||||
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
|
||||
import i18n from 'i18n-js';
|
||||
import LogoutDialog from "../../components/Amicale/LogoutDialog";
|
||||
import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton";
|
||||
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
|
||||
import {Collapsible} from "react-navigation-collapsible";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
theme: Object,
|
||||
collapsibleStack: Collapsible,
|
||||
}
|
||||
|
||||
type State = {
|
||||
|
|
@ -56,20 +52,12 @@ class ProfileScreen extends React.Component<Props, State> {
|
|||
|
||||
getScreen = (data: Object) => {
|
||||
this.data = data[0];
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
<Animated.FlatList
|
||||
<View>
|
||||
{/*$FlowFixMe*/}
|
||||
<FlatList
|
||||
renderItem={this.getRenderItem}
|
||||
data={this.flatListData}
|
||||
// Animations
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{
|
||||
paddingTop: containerPaddingTop,
|
||||
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT,
|
||||
minHeight: '100%'
|
||||
}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
/>
|
||||
<LogoutDialog
|
||||
{...this.props}
|
||||
|
|
@ -335,4 +323,4 @@ const styles = StyleSheet.create({
|
|||
|
||||
});
|
||||
|
||||
export default withCollapsible(withTheme(ProfileScreen));
|
||||
export default withTheme(ProfileScreen);
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ import AnimatedFAB from "../../components/Animations/AnimatedFAB";
|
|||
import {StackNavigationProp} from "@react-navigation/stack";
|
||||
import type {CustomTheme} from "../../managers/ThemeManager";
|
||||
import {View} from "react-native-animatable";
|
||||
import {HiddenItem} from "react-navigation-header-buttons";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import LogoutDialog from "../../components/Amicale/LogoutDialog";
|
||||
// import DATA from "../dashboard_data.json";
|
||||
|
||||
|
||||
|
|
@ -98,32 +95,21 @@ type Props = {
|
|||
theme: CustomTheme,
|
||||
}
|
||||
|
||||
type State = {
|
||||
dialogVisible: boolean,
|
||||
}
|
||||
|
||||
/**
|
||||
* Class defining the app's home screen
|
||||
*/
|
||||
class HomeScreen extends React.Component<Props, State> {
|
||||
class HomeScreen extends React.Component<Props> {
|
||||
|
||||
colors: Object;
|
||||
|
||||
isLoggedIn: boolean | null;
|
||||
|
||||
fabRef: { current: null | AnimatedFAB };
|
||||
currentNewFeed: Array<feedItem>;
|
||||
|
||||
state = {
|
||||
dialogVisible: false,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.colors = props.theme.colors;
|
||||
this.fabRef = React.createRef();
|
||||
this.currentNewFeed = [];
|
||||
this.isLoggedIn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -144,12 +130,9 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
onScreenFocus = () => {
|
||||
if (ConnectionManager.getInstance().isLoggedIn() !== this.isLoggedIn) {
|
||||
this.isLoggedIn = ConnectionManager.getInstance().isLoggedIn();
|
||||
this.props.navigation.setOptions({
|
||||
headerRight: this.getHeaderButton,
|
||||
});
|
||||
}
|
||||
this.props.navigation.setOptions({
|
||||
headerRight: this.getHeaderButton,
|
||||
});
|
||||
// handle link open when home is not focused or created
|
||||
this.handleNavigationParams();
|
||||
};
|
||||
|
|
@ -165,43 +148,25 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
getHeaderButton = () => {
|
||||
let onPressLog = () => this.props.navigation.navigate("login");
|
||||
let logIcon = "login";
|
||||
let logColor = this.props.theme.colors.primary;
|
||||
if (this.isLoggedIn) {
|
||||
onPressLog = () => this.showDisconnectDialog();
|
||||
logIcon = "logout";
|
||||
logColor = this.props.theme.colors.text;
|
||||
}
|
||||
|
||||
const onPressSettings = () => this.props.navigation.navigate("settings");
|
||||
const onPressAbout = () => this.props.navigation.navigate("about");
|
||||
return <MaterialHeaderButtons>
|
||||
<Item title="log" iconName={logIcon} color={logColor} onPress={onPressLog}/>
|
||||
<HiddenItem title={i18n.t("screens.settings")} iconName={"settings"} onPress={onPressSettings}/>
|
||||
<HiddenItem title={i18n.t("screens.about")} iconName={"information"} onPress={onPressAbout}/>
|
||||
<Item title="settings" iconName={"settings"} onPress={onPressSettings}/>
|
||||
<Item title="information" iconName={"information"} onPress={onPressAbout}/>
|
||||
</MaterialHeaderButtons>;
|
||||
};
|
||||
|
||||
showDisconnectDialog = () => this.setState({dialogVisible: true});
|
||||
|
||||
hideDisconnectDialog = () => this.setState({dialogVisible: false});
|
||||
|
||||
onProxiwashClick = () => {
|
||||
this.props.navigation.navigate("proxiwash");
|
||||
};
|
||||
|
||||
onProximoClick = () => {
|
||||
this.props.navigation.navigate('services', {screen: "index"});
|
||||
this.props.navigation.navigate("proximo");
|
||||
};
|
||||
|
||||
onTutorInsaClick = () => {
|
||||
this.props.navigation.navigate('services', {screen: "index"});
|
||||
};
|
||||
onTutorInsaClick = () => this.props.navigation.navigate('tutorinsa');
|
||||
|
||||
onMenuClick = () => {
|
||||
this.props.navigation.navigate('self-menu');
|
||||
};
|
||||
onMenuClick = () => this.props.navigation.navigate('self-menu');
|
||||
|
||||
/**
|
||||
* Creates the dataset to be used in the FlatList
|
||||
|
|
@ -279,7 +244,7 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
},
|
||||
{
|
||||
id: 'today_menu',
|
||||
data: dashboardData == null ? [] : dashboardData.today_menu,
|
||||
data: dashboardData == null ? 0 : dashboardData.today_menu,
|
||||
icon: 'silverware-fork-knife',
|
||||
color: this.colors.menuColor,
|
||||
onPress: this.onMenuClick,
|
||||
|
|
@ -312,7 +277,7 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
getDashboardActions() {
|
||||
return <ActionsDashBoardItem {...this.props} isLoggedIn={this.isLoggedIn}/>;
|
||||
return <ActionsDashBoardItem {...this.props}/>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -442,11 +407,8 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
getDashboardEvent(content: Array<event>) {
|
||||
let futureEvents = this.getFutureEvents(content);
|
||||
let displayEvent = this.getDisplayEvent(futureEvents);
|
||||
// const clickPreviewAction = () =>
|
||||
// this.props.navigation.navigate('students', {
|
||||
// screen: 'planning-information',
|
||||
// params: {data: displayEvent}
|
||||
// });
|
||||
const clickPreviewAction = () =>
|
||||
this.props.navigation.navigate('home-planning-information', {data: displayEvent});
|
||||
return (
|
||||
<DashboardItem
|
||||
eventNumber={futureEvents.length}
|
||||
|
|
@ -454,7 +416,7 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
>
|
||||
<PreviewEventDashboardItem
|
||||
event={displayEvent != null ? displayEvent : undefined}
|
||||
clickAction={this.onEventContainerClick}
|
||||
clickAction={clickPreviewAction}
|
||||
/>
|
||||
</DashboardItem>
|
||||
);
|
||||
|
|
@ -560,11 +522,6 @@ class HomeScreen extends React.Component<Props, State> {
|
|||
icon="qrcode-scan"
|
||||
onPress={this.openScanner}
|
||||
/>
|
||||
<LogoutDialog
|
||||
{...this.props}
|
||||
visible={this.state.dialogVisible}
|
||||
onDismiss={this.hideDisconnectDialog}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
85
src/screens/Insa/InsaHomeScreen.js
Normal file
85
src/screens/Insa/InsaHomeScreen.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {ScrollView, StyleSheet} from "react-native";
|
||||
import {Button, withTheme} from 'react-native-paper';
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
route: Object,
|
||||
}
|
||||
|
||||
type State = {}
|
||||
|
||||
class InsaHomeScreen extends React.Component<Props, State> {
|
||||
|
||||
state = {};
|
||||
|
||||
colors: Object;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.colors = props.theme.colors;
|
||||
}
|
||||
|
||||
render() {
|
||||
const nav = this.props.navigation;
|
||||
return (
|
||||
<ScrollView>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("self-menu")}
|
||||
>
|
||||
RU
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("available-rooms")}
|
||||
>
|
||||
AVAILABLE ROOMS
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("bib")}
|
||||
>
|
||||
BIB
|
||||
</Button>
|
||||
<Button// TODO create webview
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("self-menu")}
|
||||
>
|
||||
EMAIL
|
||||
</Button>
|
||||
<Button// TODO create webview
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("self-menu")}
|
||||
>
|
||||
ENT
|
||||
</Button>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
header: {
|
||||
fontSize: 36,
|
||||
marginBottom: 48
|
||||
},
|
||||
textInput: {},
|
||||
btnContainer: {
|
||||
marginTop: 5,
|
||||
marginBottom: 10,
|
||||
}
|
||||
});
|
||||
|
||||
export default withTheme(InsaHomeScreen);
|
||||
|
|
@ -10,8 +10,6 @@ type Props = {
|
|||
navigation: Object,
|
||||
};
|
||||
|
||||
const LOGO = "https://etud.insa-toulouse.fr/~amicale_app/images/proximo-logo.png";
|
||||
|
||||
/**
|
||||
* Class defining the proximo about screen.
|
||||
*/
|
||||
|
|
@ -29,8 +27,9 @@ export default class ProximoAboutScreen extends React.Component<Props> {
|
|||
alignItems: 'center'
|
||||
}}>
|
||||
<Image
|
||||
source={{uri: LOGO}}
|
||||
style={{height: '100%', width: '100%', resizeMode: "contain"}}/>
|
||||
source={require('../../../assets/proximo-logo.png')}
|
||||
style={{flex: 1, resizeMode: "contain"}}
|
||||
resizeMode="contain"/>
|
||||
</View>
|
||||
<Text>{i18n.t('proximoScreen.description')}</Text>
|
||||
<Card style={{margin: 5}}>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ type Props = {
|
|||
navigation: Object,
|
||||
};
|
||||
|
||||
const LOGO = "https://etud.insa-toulouse.fr/~amicale_app/images/proxiwash-logo.png";
|
||||
|
||||
/**
|
||||
* Class defining the proxiwash about screen.
|
||||
*/
|
||||
|
|
@ -29,8 +27,9 @@ export default class ProxiwashAboutScreen extends React.Component<Props> {
|
|||
alignItems: 'center'
|
||||
}}>
|
||||
<Image
|
||||
source={{uri: LOGO}}
|
||||
style={{height: '100%', width: '100%', resizeMode: "contain"}}/>
|
||||
source={require('../../../assets/proxiwash-logo.png')}
|
||||
style={{flex: 1, resizeMode: "contain"}}
|
||||
resizeMode="contain"/>
|
||||
</View>
|
||||
<Text>{i18n.t('proxiwashScreen.description')}</Text>
|
||||
<Card style={{margin: 5}}>
|
||||
|
|
|
|||
|
|
@ -1,291 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import type {cardList} from "../../components/Lists/CardList/CardList";
|
||||
import CardList from "../../components/Lists/CardList/CardList";
|
||||
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
import {Collapsible} from "react-navigation-collapsible";
|
||||
import {CommonActions} from "@react-navigation/native";
|
||||
import {Animated, View} from "react-native";
|
||||
import {Avatar, Button, Card, Divider, List, Title, TouchableRipple, withTheme} from "react-native-paper";
|
||||
import type {CustomTheme} from "../../managers/ThemeManager";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import i18n from 'i18n-js';
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
route: Object,
|
||||
collapsibleStack: Collapsible,
|
||||
theme: CustomTheme,
|
||||
}
|
||||
const BIB_IMAGE = "https://scontent-cdg2-1.xx.fbcdn.net/v/t1.0-9/50695561_2124263197597162_2325349608210825216_n.jpg?_nc_cat=109&_nc_sid=8bfeb9&_nc_ohc=tmcV6FWO7_kAX9vfWHU&_nc_ht=scontent-cdg2-1.xx&oh=3b81c76e46b49f7c3a033ea3b07ec212&oe=5EC59B4D";
|
||||
const RU_IMAGE = "https://scontent-cdg2-1.xx.fbcdn.net/v/t1.0-9/47123773_2041883702501779_5289372776166064128_o.jpg?_nc_cat=100&_nc_sid=cdbe9c&_nc_ohc=dpuBGlIIy_EAX8CyC0l&_nc_ht=scontent-cdg2-1.xx&oh=5c5bb4f0c7f12b554246f7c9b620a5f3&oe=5EC4DB31";
|
||||
const ROOM_IMAGE = "https://scontent-cdt1-1.xx.fbcdn.net/v/t1.0-9/47041013_2043521689004647_316124496522117120_n.jpg?_nc_cat=103&_nc_sid=8bfeb9&_nc_ohc=bIp8OVJvvSEAX8mKnDZ&_nc_ht=scontent-cdt1-1.xx&oh=b4fef72a645804a849ad30e9e20fca12&oe=5EC29309";
|
||||
const EMAIL_IMAGE = "https://etud-mel.insa-toulouse.fr/webmail/images/logo-bluemind.png";
|
||||
const ENT_IMAGE = "https://ent.insa-toulouse.fr/media/org/jasig/portal/layout/tab-column/xhtml-theme/insa/institutional/LogoInsa.png";
|
||||
|
||||
const PROXIMO_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/proximo-logo.png"
|
||||
const WIKETUD_LINK = "https://wiki.etud.insa-toulouse.fr/resources/assets/wiketud.png?ff051";
|
||||
const AMICALE_IMAGE = require("../../../assets/amicale.png");
|
||||
const EE_IMAGE = "https://etud.insa-toulouse.fr/~eeinsat/wp-content/uploads/2019/09/logo-blanc.png";
|
||||
const TUTORINSA_IMAGE = "https://www.etud.insa-toulouse.fr/~tutorinsa/public/images/logo-gray.png";
|
||||
|
||||
export type listItem = {
|
||||
title: string,
|
||||
description: string,
|
||||
image: string | number,
|
||||
shouldLogin: boolean,
|
||||
content: cardList,
|
||||
}
|
||||
|
||||
type State = {
|
||||
isLoggedIn: boolean,
|
||||
}
|
||||
|
||||
class ServicesScreen extends React.Component<Props, State> {
|
||||
|
||||
amicaleDataset: cardList;
|
||||
studentsDataset: cardList;
|
||||
insaDataset: cardList;
|
||||
|
||||
finalDataset: Array<listItem>
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const nav = props.navigation;
|
||||
this.amicaleDataset = [
|
||||
{
|
||||
title: i18n.t('screens.clubsAbout'),
|
||||
subtitle: "CLUB LIST",
|
||||
image: AMICALE_IMAGE,
|
||||
onPress: () => nav.navigate("club-list"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.profile'),
|
||||
subtitle: "PROFIL",
|
||||
image: AMICALE_IMAGE,
|
||||
onPress: () => nav.navigate("profile"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.amicaleAbout'),
|
||||
subtitle: "CONTACT",
|
||||
image: AMICALE_IMAGE,
|
||||
onPress: () => nav.navigate("amicale-contact"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.vote'),
|
||||
subtitle: "ELECTIONS",
|
||||
image: AMICALE_IMAGE,
|
||||
onPress: () => nav.navigate("vote"),
|
||||
},
|
||||
];
|
||||
this.studentsDataset = [
|
||||
{
|
||||
title: i18n.t('screens.proximo'),
|
||||
subtitle: "proximo",
|
||||
image: PROXIMO_IMAGE,
|
||||
onPress: () => nav.navigate("proximo"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.amicaleWebsite'),
|
||||
subtitle: "AMICALE",
|
||||
image: AMICALE_IMAGE,
|
||||
onPress: () => nav.navigate("amicale-website"),
|
||||
},
|
||||
{
|
||||
title: "Wiketud",
|
||||
subtitle: "wiketud",
|
||||
image: WIKETUD_LINK,
|
||||
onPress: () => nav.navigate("wiketud"),
|
||||
},
|
||||
{
|
||||
title: "Élus Étudiants",
|
||||
subtitle: "ELUS ETUDIANTS",
|
||||
image: EE_IMAGE,
|
||||
onPress: () => nav.navigate("elus-etudiants"),
|
||||
},
|
||||
{
|
||||
title: "Tutor'INSA",
|
||||
subtitle: "TUTOR INSA",
|
||||
image: TUTORINSA_IMAGE,
|
||||
onPress: () => nav.navigate("tutorinsa"),
|
||||
},
|
||||
];
|
||||
this.insaDataset = [
|
||||
{
|
||||
title: i18n.t('screens.menuSelf'),
|
||||
subtitle: "the ru",
|
||||
image: RU_IMAGE,
|
||||
onPress: () => nav.navigate("self-menu"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.availableRooms'),
|
||||
subtitle: "ROOMS",
|
||||
image: ROOM_IMAGE,
|
||||
onPress: () => nav.navigate("available-rooms"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.bib'),
|
||||
subtitle: "BIB",
|
||||
image: BIB_IMAGE,
|
||||
onPress: () => nav.navigate("bib"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.bluemind'),
|
||||
subtitle: "EMAIL",
|
||||
image: EMAIL_IMAGE,
|
||||
onPress: () => nav.navigate("bluemind"),
|
||||
},
|
||||
{
|
||||
title: i18n.t('screens.ent'),
|
||||
subtitle: "ENT",
|
||||
image: ENT_IMAGE,
|
||||
onPress: () => nav.navigate("ent"),
|
||||
},
|
||||
];
|
||||
this.finalDataset = [
|
||||
{
|
||||
title: i18n.t("servicesScreen.amicale"),
|
||||
description: "LOGIN",
|
||||
image: AMICALE_IMAGE,
|
||||
shouldLogin: true,
|
||||
content: this.amicaleDataset
|
||||
},
|
||||
{
|
||||
title: i18n.t("servicesScreen.students"),
|
||||
description: "SERVICES OFFERED BY STUDENTS",
|
||||
image: 'account-group',
|
||||
shouldLogin: false,
|
||||
content: this.studentsDataset
|
||||
},
|
||||
{
|
||||
title: i18n.t("servicesScreen.insa"),
|
||||
description: "SERVICES OFFERED BY INSA",
|
||||
image: 'school',
|
||||
shouldLogin: false,
|
||||
content: this.insaDataset
|
||||
},
|
||||
];
|
||||
this.state = {
|
||||
isLoggedIn: ConnectionManager.getInstance().isLoggedIn()
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.navigation.addListener('focus', this.onFocus);
|
||||
|
||||
}
|
||||
|
||||
onFocus = () => {
|
||||
this.handleNavigationParams();
|
||||
this.setState({isLoggedIn: ConnectionManager.getInstance().isLoggedIn()})
|
||||
}
|
||||
|
||||
handleNavigationParams() {
|
||||
if (this.props.route.params != null) {
|
||||
if (this.props.route.params.nextScreen != null) {
|
||||
this.props.navigation.navigate(this.props.route.params.nextScreen);
|
||||
// reset params to prevent infinite loop
|
||||
this.props.navigation.dispatch(CommonActions.setParams({nextScreen: null}));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getAvatar(props, source: string | number) {
|
||||
if (typeof source === "number")
|
||||
return <Avatar.Image
|
||||
{...props}
|
||||
size={48}
|
||||
source={AMICALE_IMAGE}
|
||||
style={{backgroundColor: 'transparent'}}
|
||||
/>
|
||||
else
|
||||
return <Avatar.Icon
|
||||
{...props}
|
||||
size={48}
|
||||
icon={source}
|
||||
color={this.props.theme.colors.primary}
|
||||
style={{backgroundColor: 'transparent'}}
|
||||
/>
|
||||
}
|
||||
|
||||
getLoginMessage() {
|
||||
return (
|
||||
<View>
|
||||
<Title style={{
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
}}>
|
||||
{i18n.t("servicesScreen.notLoggedIn")}
|
||||
</Title>
|
||||
<Button
|
||||
icon="login"
|
||||
mode="contained"
|
||||
onPress={() => this.props.navigation.navigate("login")}
|
||||
style={{
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
}}>
|
||||
{i18n.t("screens.login")}
|
||||
</Button>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
renderItem = ({item}: { item: listItem }) => {
|
||||
const shouldShowLogin = !this.state.isLoggedIn && item.shouldLogin;
|
||||
return (
|
||||
<TouchableRipple
|
||||
style={{
|
||||
margin: 5,
|
||||
marginBottom: 20,
|
||||
}}
|
||||
onPress={shouldShowLogin
|
||||
? undefined
|
||||
: () => this.props.navigation.navigate("services-section", {data: item})}
|
||||
>
|
||||
<View>
|
||||
<Card.Title
|
||||
title={item.title}
|
||||
left={(props) => this.getAvatar(props, item.image)}
|
||||
right={shouldShowLogin
|
||||
? undefined
|
||||
: (props) => <List.Icon {...props} icon="chevron-right"/>}
|
||||
/>
|
||||
{
|
||||
shouldShowLogin
|
||||
? this.getLoginMessage()
|
||||
: <CardList
|
||||
dataset={item.content}
|
||||
isHorizontal={true}
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
</TouchableRipple>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
keyExtractor = (item: listItem) => {
|
||||
return item.title;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
|
||||
return <Animated.FlatList
|
||||
data={this.finalDataset}
|
||||
renderItem={this.renderItem}
|
||||
keyExtractor={this.keyExtractor}
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{
|
||||
paddingTop: containerPaddingTop,
|
||||
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
|
||||
}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
ItemSeparatorComponent={() => <Divider/>}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
export default withCollapsible(withTheme(ServicesScreen));
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import CardList from "../../components/Lists/CardList/CardList";
|
||||
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
|
||||
import {withCollapsible} from "../../utils/withCollapsible";
|
||||
import {Collapsible} from "react-navigation-collapsible";
|
||||
import {CommonActions} from "@react-navigation/native";
|
||||
import ConnectionManager from "../../managers/ConnectionManager";
|
||||
import type {listItem} from "./ServicesScreen";
|
||||
import ErrorView from "../../components/Screens/ErrorView";
|
||||
import {ERROR_TYPE} from "../../utils/WebData";
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
route: Object,
|
||||
collapsibleStack: Collapsible,
|
||||
}
|
||||
|
||||
type State = {
|
||||
isLoggedIn: boolean,
|
||||
}
|
||||
|
||||
class ServicesSectionScreen extends React.Component<Props, State> {
|
||||
|
||||
finalDataset: listItem;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleNavigationParams();
|
||||
this.state = {
|
||||
isLoggedIn: ConnectionManager.getInstance().isLoggedIn(),
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.navigation.addListener('focus', this.onFocus);
|
||||
|
||||
}
|
||||
|
||||
onFocus = () => {
|
||||
this.setState({isLoggedIn: ConnectionManager.getInstance().isLoggedIn()})
|
||||
}
|
||||
|
||||
handleNavigationParams() {
|
||||
if (this.props.route.params != null) {
|
||||
if (this.props.route.params.data != null) {
|
||||
this.finalDataset = this.props.route.params.data;
|
||||
// reset params to prevent infinite loop
|
||||
this.props.navigation.dispatch(CommonActions.setParams({data: null}));
|
||||
this.props.navigation.setOptions({
|
||||
headerTitle: this.finalDataset.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
|
||||
if (!this.state.isLoggedIn && this.finalDataset.shouldLogin)
|
||||
return <ErrorView {...this.props} errorCode={ERROR_TYPE.BAD_TOKEN}/>;
|
||||
else
|
||||
return <CardList
|
||||
dataset={this.finalDataset.content}
|
||||
isHorizontal={false}
|
||||
onScroll={onScroll}
|
||||
contentContainerStyle={{
|
||||
paddingTop: containerPaddingTop,
|
||||
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
|
||||
}}
|
||||
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
export default withCollapsible(ServicesSectionScreen);
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import WebViewScreen from "../../components/Screens/WebViewScreen";
|
||||
|
||||
const URL = 'https://etud-mel.insa-toulouse.fr/webmail/';
|
||||
/**
|
||||
* Class defining the app's available rooms screen.
|
||||
* This screen uses a webview to render the page
|
||||
*/
|
||||
export const BlueMindWebsiteScreen = (props: Object) => {
|
||||
return (
|
||||
<WebViewScreen
|
||||
{...props}
|
||||
url={URL}/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import WebViewScreen from "../../components/Screens/WebViewScreen";
|
||||
|
||||
const URL = 'https://ent.insa-toulouse.fr/';
|
||||
/**
|
||||
* Class defining the app's available rooms screen.
|
||||
* This screen uses a webview to render the page
|
||||
*/
|
||||
export const ENTWebsiteScreen = (props: Object) => {
|
||||
return (
|
||||
<WebViewScreen
|
||||
{...props}
|
||||
url={URL}/>
|
||||
);
|
||||
};
|
||||
|
||||
91
src/screens/Websites/WebsitesHomeScreen.js
Normal file
91
src/screens/Websites/WebsitesHomeScreen.js
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
// @flow
|
||||
|
||||
import * as React from 'react';
|
||||
import {ScrollView, StyleSheet} from "react-native";
|
||||
import {Button, withTheme} from 'react-native-paper';
|
||||
|
||||
type Props = {
|
||||
navigation: Object,
|
||||
route: Object,
|
||||
}
|
||||
|
||||
type State = {}
|
||||
|
||||
class WebsitesHomeScreen extends React.Component<Props, State> {
|
||||
|
||||
state = {};
|
||||
|
||||
colors: Object;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.colors = props.theme.colors;
|
||||
}
|
||||
|
||||
render() {
|
||||
const nav = this.props.navigation;
|
||||
return (
|
||||
<ScrollView>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("amicale-website")}
|
||||
>
|
||||
AMICALE
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("elus-etudiants")}
|
||||
>
|
||||
ELUS ETUDIANTS
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("tutorinsa")}
|
||||
>
|
||||
TUTOR INSA
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("wiketud")}
|
||||
>
|
||||
WIKETUD
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("proximo")}
|
||||
>
|
||||
PROXIMO
|
||||
</Button>
|
||||
<Button
|
||||
icon={"information"}
|
||||
onPress={() => nav.navigate("planning")}
|
||||
>
|
||||
PLANNING
|
||||
</Button>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
card: {
|
||||
margin: 10,
|
||||
},
|
||||
header: {
|
||||
fontSize: 36,
|
||||
marginBottom: 48
|
||||
},
|
||||
textInput: {},
|
||||
btnContainer: {
|
||||
marginTop: 5,
|
||||
marginBottom: 10,
|
||||
}
|
||||
});
|
||||
|
||||
export default withTheme(WebsitesHomeScreen);
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
{
|
||||
"screens": {
|
||||
"home": "Home",
|
||||
"planning": "Events",
|
||||
"planning": "Planning",
|
||||
"planningDisplayScreen": "Event details",
|
||||
"clubDisplayScreen": "Club details",
|
||||
"feedDisplayScreen": "Details",
|
||||
"clubsAbout": "Clubs",
|
||||
"amicaleAbout": "Contact",
|
||||
"amicaleWebsite": "Amicale's website",
|
||||
"amicaleAbout": "The Amicale",
|
||||
"proxiwash": "Proxiwash",
|
||||
"services": "Services",
|
||||
"proximo": "Proximo",
|
||||
"proximoArticles": "Articles",
|
||||
"menuSelf": "RU Menu",
|
||||
|
|
@ -97,11 +95,28 @@
|
|||
"todayEventsSubtitleNA": "No events today",
|
||||
"todayEventsSubtitle": " event coming today",
|
||||
"todayEventsSubtitlePlural": " events coming today",
|
||||
"amicaleTitle": "The Amicale",
|
||||
"amicaleConnect": "Login",
|
||||
"amicaleConnected": "See available services"
|
||||
"proximoTitle": "Proximo",
|
||||
"proximoSubtitleNA": "No articles available",
|
||||
"proximoSubtitle": " article available",
|
||||
"proximoSubtitlePlural": " articles available",
|
||||
"tutorinsaSubtitleNA": "No tutorial available",
|
||||
"tutorinsaSubtitle": " tutorial available",
|
||||
"tutorinsaSubtitlePlural": " tutorials available",
|
||||
"proxiwashTitle": "Available machines",
|
||||
"proxiwashSubtitleNA": "No machines available",
|
||||
"proxiwashSubtitle1": " dryer",
|
||||
"proxiwashSubtitle1Plural": " dryers",
|
||||
"proxiwashSubtitle2": " washer",
|
||||
"proxiwashSubtitle2Plural": " washers",
|
||||
"menuTitle": "Today's menu",
|
||||
"menuSubtitleNA": "No menu available",
|
||||
"menuSubtitle": "Click here to see the menu"
|
||||
}
|
||||
},
|
||||
"planningScreen": {
|
||||
"wipTitle": "WORK IN PROGRESS",
|
||||
"wipSubtitle": "Soon, every event at the INSA Toulouse in one place !"
|
||||
},
|
||||
"aboutScreen": {
|
||||
"appstore": "See on the Appstore",
|
||||
"playstore": "See on the Playstore",
|
||||
|
|
@ -278,7 +293,7 @@
|
|||
"animation": "Animation",
|
||||
"clubs": "Clubs",
|
||||
"event": "Events",
|
||||
"tech": "Technique",
|
||||
"tech" : "Technique",
|
||||
"communication": "Communication",
|
||||
"intraSchools": "Alumni / IAT",
|
||||
"publicRelations": "Public Relations"
|
||||
|
|
@ -296,28 +311,28 @@
|
|||
"tease": {
|
||||
"title": "Elections incoming",
|
||||
"subtitle": "Be ready to vote!",
|
||||
"message": "Vote start:"
|
||||
"message" : "Vote start:"
|
||||
},
|
||||
"wait": {
|
||||
"titleSubmitted": "Vote submitted!",
|
||||
"titleEnded": "Votes closed",
|
||||
"subtitle": "Waiting for results...",
|
||||
"messageSubmitted": "Vote submitted successfully.",
|
||||
"messageVoted": "Thank you for your participation.",
|
||||
"messageDate": "Results available:",
|
||||
"messageDateUndefined": "Results will be available shortly"
|
||||
"subtitle" : "Waiting for results...",
|
||||
"messageSubmitted" : "Vote submitted successfully.",
|
||||
"messageVoted" : "Thank you for your participation.",
|
||||
"messageDate" : "Results available:",
|
||||
"messageDateUndefined" : "Results will be available shortly"
|
||||
},
|
||||
"results": {
|
||||
"title": "Results",
|
||||
"subtitle": "Available until:",
|
||||
"totalVotes": "Total votes:",
|
||||
"votes": "votes"
|
||||
"totalVotes" : "Total votes:",
|
||||
"votes" : "votes"
|
||||
},
|
||||
"title": {
|
||||
"title": "The Elections",
|
||||
"subtitle": "Why your vote is important",
|
||||
"paragraph1": "The Amicale's elections is the right moment for you to choose the next team, which will handle different projects on the campus, help organizing your favorite events, animate the campus life during the whole year, and relay your ideas to the administration, so that your campus life is the most enjoyable possible!\nYour turn to make a change!\uD83D\uDE09",
|
||||
"paragraph2": "Note: If there is only one list, it is still important to vote to show your support, so that the administration knows the current list is supported by students. It is always a plus when taking difficult decisions! \uD83D\uDE09"
|
||||
"paragraph1" : "The Amicale's elections is the right moment for you to choose the next team, which will handle different projects on the campus, help organizing your favorite events, animate the campus life during the whole year, and relay your ideas to the administration, so that your campus life is the most enjoyable possible!\nYour turn to make a change!\uD83D\uDE09",
|
||||
"paragraph2" : "Note: If there is only one list, it is still important to vote to show your support, so that the administration knows the current list is supported by students. It is always a plus when taking difficult decisions! \uD83D\uDE09"
|
||||
}
|
||||
},
|
||||
"dialog": {
|
||||
|
|
@ -382,11 +397,5 @@
|
|||
"time": "Time: ",
|
||||
"exit": "leave Game"
|
||||
}
|
||||
},
|
||||
"servicesScreen": {
|
||||
"amicale": "The Amicale",
|
||||
"students": "Student services",
|
||||
"insa": "INSA services",
|
||||
"notLoggedIn": "Not logged in"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
{
|
||||
"screens": {
|
||||
"home": "Accueil",
|
||||
"planning": "Événements",
|
||||
"planning": "Planning",
|
||||
"planningDisplayScreen": "Détails",
|
||||
"clubDisplayScreen": "Détails",
|
||||
"feedDisplayScreen": "Détails",
|
||||
"clubsAbout": "Les Clubs",
|
||||
"amicaleAbout": "Contact",
|
||||
"amicaleWebsite": "Site de l'Amicale",
|
||||
"amicaleAbout": "L' Amicale",
|
||||
"proxiwash": "Proxiwash",
|
||||
"services": "Services",
|
||||
"proximo": "Proximo",
|
||||
"proximoArticles": "Articles",
|
||||
"menuSelf": "Menu du RU",
|
||||
|
|
@ -97,11 +95,28 @@
|
|||
"todayEventsSubtitleNA": "Pas d'événement",
|
||||
"todayEventsSubtitle": " événement aujourd'hui",
|
||||
"todayEventsSubtitlePlural": " événements aujourd'hui",
|
||||
"amicaleTitle": "L'Amicale",
|
||||
"amicaleConnect": "Se connecter",
|
||||
"amicaleConnected": "Voir les services disponibles"
|
||||
"proximoTitle": "Proximo",
|
||||
"proximoSubtitleNA": "pas d'article en vente",
|
||||
"proximoSubtitle": " article disponible",
|
||||
"proximoSubtitlePlural": " articles disponibles",
|
||||
"tutorinsaSubtitleNA": "Aucun tutorat disponible",
|
||||
"tutorinsaSubtitle": " tutorat disponible",
|
||||
"tutorinsaSubtitlePlural": " tutorats disponibles",
|
||||
"proxiwashTitle": "Machines disponibles",
|
||||
"proxiwashSubtitleNA": "Pas de machine disponible",
|
||||
"proxiwashSubtitle1": " sèche-linge",
|
||||
"proxiwashSubtitle1Plural": " sèche-linges",
|
||||
"proxiwashSubtitle2": " lave-linge",
|
||||
"proxiwashSubtitle2Plural": " lave-linges",
|
||||
"menuTitle": "Menu d'aujourd'hui",
|
||||
"menuSubtitleNA": "Pas de menu disponible",
|
||||
"menuSubtitle": "Cliquez ici pour voir le menu"
|
||||
}
|
||||
},
|
||||
"planningScreen": {
|
||||
"wipTitle": "WORK IN PROGRESS",
|
||||
"wipSubtitle": "Bientôt, tous les évènements de l'INSA Toulouse en un seul endroit !"
|
||||
},
|
||||
"aboutScreen": {
|
||||
"appstore": "Voir sur l'Appstore",
|
||||
"playstore": "Voir sur le Playstore",
|
||||
|
|
@ -278,7 +293,7 @@
|
|||
"animation": "Animation",
|
||||
"clubs": "Clubs",
|
||||
"event": "Événements",
|
||||
"tech": "Technique",
|
||||
"tech" : "Technique",
|
||||
"communication": "Communication",
|
||||
"intraSchools": "Alumni / IAT",
|
||||
"publicRelations": "Relations Publiques"
|
||||
|
|
@ -296,28 +311,28 @@
|
|||
"tease": {
|
||||
"title": "Les élections arrivent",
|
||||
"subtitle": "Préparez vous à voter !",
|
||||
"message": "Début des votes :"
|
||||
"message" : "Début des votes :"
|
||||
},
|
||||
"wait": {
|
||||
"titleSubmitted": "Vote envoyé !",
|
||||
"titleEnded": "Votes fermés",
|
||||
"subtitle": "Attente des résultats...",
|
||||
"messageSubmitted": "Votre vote a bien été envoyé.",
|
||||
"messageVoted": "Merci pour votre participation.",
|
||||
"messageDate": "Disponibilité des résultats :",
|
||||
"messageDateUndefined": "les résultats seront disponibles sous peu."
|
||||
"subtitle" : "Attente des résultats...",
|
||||
"messageSubmitted" : "Votre vote a bien été envoyé.",
|
||||
"messageVoted" : "Merci pour votre participation.",
|
||||
"messageDate" : "Disponibilité des résultats :",
|
||||
"messageDateUndefined" : "les résultats seront disponibles sous peu."
|
||||
},
|
||||
"results": {
|
||||
"title": "Résultats",
|
||||
"subtitle": "Disponibles jusqu'à :",
|
||||
"totalVotes": "Nombre total de votes :",
|
||||
"votes": "votes"
|
||||
"totalVotes" : "Nombre total de votes :",
|
||||
"votes" : "votes"
|
||||
},
|
||||
"title": {
|
||||
"title": "Les Élections",
|
||||
"subtitle": "Pourquoi votre vote est important",
|
||||
"paragraph1": "Les élections de l'amicale, c'est le moment pour vous de choisir la prochaine équipe qui portera les différents projets du campus, qui soutiendra les organisations de vos événements favoris, qui vous proposera des animations tout au long de l'année, et qui poussera vos idées à l’administration pour que la vie de campus soit des plus riches !\nAlors à vous de jouer ! \uD83D\uDE09",
|
||||
"paragraph2": "NB : Si par cas il n'y a qu'une liste qui se présente, il est important que tout le monde vote, afin qui la liste puisse montrer à l’administration que les INSAiens la soutiennent ! Ça compte toujours pour les décisions difficiles ! \uD83D\uDE09"
|
||||
"paragraph1" : "Les élections de l'amicale, c'est le moment pour vous de choisir la prochaine équipe qui portera les différents projets du campus, qui soutiendra les organisations de vos événements favoris, qui vous proposera des animations tout au long de l'année, et qui poussera vos idées à l’administration pour que la vie de campus soit des plus riches !\nAlors à vous de jouer ! \uD83D\uDE09",
|
||||
"paragraph2" : "NB : Si par cas il n'y a qu'une liste qui se présente, il est important que tout le monde vote, afin qui la liste puisse montrer à l’administration que les INSAiens la soutiennent ! Ça compte toujours pour les décisions difficiles ! \uD83D\uDE09"
|
||||
}
|
||||
},
|
||||
"dialog": {
|
||||
|
|
@ -382,11 +397,5 @@
|
|||
"time": "Temps: ",
|
||||
"exit": "Quitter"
|
||||
}
|
||||
},
|
||||
"servicesScreen": {
|
||||
"amicale": "L'Amicale",
|
||||
"students": "Services étudiants",
|
||||
"insa": "Services de l'INSA",
|
||||
"notLoggedIn": "Non connecté"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue