Compare commits

..

No commits in common. "ac9709d6668a099bfe801d63ba943affd7f1967d" and "77cc5d87465a307b41d29da3d9a6a29244249b11" have entirely different histories.

30 changed files with 839 additions and 839 deletions

6
App.js
View file

@ -9,7 +9,7 @@ import {AppLoading} from 'expo';
import type {CustomTheme} from "./src/managers/ThemeManager"; import type {CustomTheme} from "./src/managers/ThemeManager";
import ThemeManager from './src/managers/ThemeManager'; import ThemeManager from './src/managers/ThemeManager';
import {NavigationContainer} from '@react-navigation/native'; 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 {initExpoToken} from "./src/utils/Notifications";
import {Provider as PaperProvider} from 'react-native-paper'; import {Provider as PaperProvider} from 'react-native-paper';
import AprilFoolsManager from "./src/managers/AprilFoolsManager"; import AprilFoolsManager from "./src/managers/AprilFoolsManager";
@ -156,7 +156,7 @@ export default class App extends React.Component<Props, State> {
*/ */
onLoadFinished() { onLoadFinished() {
// Only show intro if this is the first time starting the app // Only show intro if this is the first time starting the app
this.createDrawerNavigator = () => <MainNavigator this.createDrawerNavigator = () => <DrawerNavigator
defaultHomeRoute={this.defaultHomeRoute} defaultHomeRoute={this.defaultHomeRoute}
defaultHomeData={this.defaultHomeData} defaultHomeData={this.defaultHomeData}
/>; />;
@ -191,7 +191,7 @@ export default class App extends React.Component<Props, State> {
return ( return (
<PaperProvider theme={this.state.currentTheme}> <PaperProvider theme={this.state.currentTheme}>
<NavigationContainer theme={this.state.currentTheme} ref={this.navigatorRef}> <NavigationContainer theme={this.state.currentTheme} ref={this.navigatorRef}>
<MainNavigator <DrawerNavigator
defaultHomeRoute={this.defaultHomeRoute} defaultHomeRoute={this.defaultHomeRoute}
defaultHomeData={this.defaultHomeData} defaultHomeData={this.defaultHomeData}
/> />

BIN
assets/drawer-cover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
assets/proximo-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

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

View file

@ -5,48 +5,36 @@ import {Avatar, Card, List, withTheme} from 'react-native-paper';
import {StyleSheet} from "react-native"; import {StyleSheet} from "react-native";
import {DrawerNavigationProp} from "@react-navigation/drawer"; import {DrawerNavigationProp} from "@react-navigation/drawer";
import type {CustomTheme} from "../../managers/ThemeManager"; import type {CustomTheme} from "../../managers/ThemeManager";
import i18n from 'i18n-js';
const ICON_AMICALE = require("../../../assets/amicale.png"); const ICON_AMICALE = require("../../../assets/amicale.png");
type Props = { type Props = {
navigation: DrawerNavigationProp, navigation: DrawerNavigationProp,
theme: CustomTheme, theme: CustomTheme,
isLoggedIn: boolean,
} }
class ActionsDashBoardItem extends React.Component<Props> { class ActionsDashBoardItem extends React.Component<Props> {
shouldComponentUpdate(nextProps: Props): boolean { shouldComponentUpdate(nextProps: Props): boolean {
return (nextProps.theme.dark !== this.props.theme.dark) return (nextProps.theme.dark !== this.props.theme.dark)
|| (nextProps.isLoggedIn !== this.props.isLoggedIn);
} }
render() { render() {
const isLoggedIn = this.props.isLoggedIn;
return ( return (
<Card style={{ <Card style={{
...styles.card, ...styles.card,
borderColor: this.props.theme.colors.primary, borderColor: this.props.theme.colors.primary,
}}> }}>
<List.Item <List.Item
title={i18n.t("homeScreen.dashboard.amicaleTitle")} title={"AMICALE"}
description={isLoggedIn description={"VOTRE COMPTE"}
? i18n.t("homeScreen.dashboard.amicaleConnected")
: i18n.t("homeScreen.dashboard.amicaleConnect")}
left={props => <Avatar.Image left={props => <Avatar.Image
{...props} {...props}
size={40} size={40}
source={ICON_AMICALE} source={ICON_AMICALE}
style={styles.avatar}/>} style={styles.avatar}/>}
right={props => <List.Icon {...props} icon={isLoggedIn right={props => <List.Icon {...props} icon="chevron-right"/>}
? "chevron-right" onPress={() => this.props.navigation.navigate("amicale-home")}
: "login"}/>}
onPress={isLoggedIn
? () => this.props.navigation.navigate("services", {
screen: 'index'
})
: () => this.props.navigation.navigate("login")}
style={styles.list} style={styles.list}
/> />
</Card> </Card>
@ -63,14 +51,12 @@ const styles = StyleSheet.create({
borderWidth: 1, borderWidth: 1,
}, },
avatar: { avatar: {
backgroundColor: 'transparent', backgroundColor: 'transparent'
marginTop: 'auto',
marginBottom: 'auto',
}, },
list: { list: {
// height: 50, // height: 50,
paddingTop: 0, paddingTop:0,
paddingBottom: 0, paddingBottom:0,
} }
}); });

View file

@ -16,6 +16,7 @@ type Props = {
}; };
const AnimatableBadge = Animatable.createAnimatableComponent(Badge); const AnimatableBadge = Animatable.createAnimatableComponent(Badge);
const AnimatableIconButton = Animatable.createAnimatableComponent(IconButton);
/** /**
* Component used to render a small dashboard item * Component used to render a small dashboard item
@ -33,7 +34,7 @@ class SmallDashboardItem extends React.Component<Props> {
const colors = props.theme.colors; const colors = props.theme.colors;
return ( return (
<View> <View>
<IconButton <AnimatableIconButton
icon={props.icon} icon={props.icon}
color={ color={
props.isAvailable props.isAvailable

View file

@ -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}
/>
);
}
}

View file

@ -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>
);
}
}

View file

@ -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>
);
}
}

View file

@ -6,13 +6,15 @@ import {HeaderButton, HeaderButtons} from 'react-navigation-header-buttons';
import {withTheme} from "react-native-paper"; import {withTheme} from "react-native-paper";
import * as Touchable from "react-native/Libraries/Components/Touchable/TouchableNativeFeedback.android"; import * as Touchable from "react-native/Libraries/Components/Touchable/TouchableNativeFeedback.android";
const MaterialHeaderButton = (props: Object) => <HeaderButton const MaterialHeaderButton = (props: Object) => (
<HeaderButton
IconComponent={MaterialCommunityIcons} IconComponent={MaterialCommunityIcons}
iconSize={26} 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)} background={Touchable.Ripple(props.theme.colors.ripple, true)}
{...props} {...props}
/>; />
);
const MaterialHeaderButtons = (props: Object) => { const MaterialHeaderButtons = (props: Object) => {
return ( return (

View 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);

View 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;

View file

@ -19,8 +19,8 @@ type State = {
const TAB_ICONS = { const TAB_ICONS = {
proxiwash: 'tshirt-crew', proxiwash: 'tshirt-crew',
services: 'account-circle', students: 'account-circle',
planning: 'calendar-range', insa: 'book',
planex: 'clock', planex: 'clock',
}; };

View file

@ -7,8 +7,7 @@ import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
import DebugScreen from '../screens/About/DebugScreen'; import DebugScreen from '../screens/About/DebugScreen';
import {createStackNavigator, TransitionPresets} from "@react-navigation/stack"; import {createStackNavigator, TransitionPresets} from "@react-navigation/stack";
import i18n from "i18n-js"; import i18n from "i18n-js";
import TabNavigator from "./TabNavigator"; import TabNavigator from "./MainTabNavigator";
import TetrisScreen from "../screens/Tetris/TetrisScreen";
const defaultScreenOptions = { const defaultScreenOptions = {
gestureEnabled: true, gestureEnabled: true,
@ -60,13 +59,6 @@ function MainStackComponent(props: { createTabNavigator: () => React.Node }) {
title: i18n.t('aboutScreen.debug') title: i18n.t('aboutScreen.debug')
}} }}
/> />
<MainStack.Screen
name="tetris"
component={TetrisScreen}
options={{
title: i18n.t("game.title"),
}}
/>
</MainStack.Navigator> </MainStack.Navigator>
); );
} }
@ -76,7 +68,7 @@ type Props = {
defaultHomeData: { [key: string]: any } defaultHomeData: { [key: string]: any }
} }
export default class MainNavigator extends React.Component<Props> { export default class DrawerNavigator extends React.Component<Props> {
createTabNavigator: () => React.Node; createTabNavigator: () => React.Node;

View file

@ -21,23 +21,23 @@ import FeedItemScreen from "../screens/Home/FeedItemScreen";
import {createCollapsibleStack} from "react-navigation-collapsible"; import {createCollapsibleStack} from "react-navigation-collapsible";
import GroupSelectionScreen from "../screens/Planex/GroupSelectionScreen"; import GroupSelectionScreen from "../screens/Planex/GroupSelectionScreen";
import CustomTabBar from "../components/Tabbar/CustomTabBar"; 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 AvailableRoomScreen from "../screens/Websites/AvailableRoomScreen";
import BibScreen from "../screens/Websites/BibScreen"; import BibScreen from "../screens/Websites/BibScreen";
import {AmicaleWebsiteScreen} from "../screens/Websites/AmicaleWebsiteScreen"; import {AmicaleWebsiteScreen} from "../screens/Websites/AmicaleWebsiteScreen";
import {ElusEtudiantsWebsiteScreen} from "../screens/Websites/ElusEtudiantsWebsiteScreen"; import {ElusEtudiantsWebsiteScreen} from "../screens/Websites/ElusEtudiantsWebsiteScreen";
import {WiketudWebsiteScreen} from "../screens/Websites/WiketudWebsiteScreen"; import {WiketudWebsiteScreen} from "../screens/Websites/WiketudWebsiteScreen";
import {TutorInsaWebsiteScreen} from "../screens/Websites/TutorInsaWebsiteScreen"; import {TutorInsaWebsiteScreen} from "../screens/Websites/TutorInsaWebsiteScreen";
import {ENTWebsiteScreen} from "../screens/Websites/ENTWebsiteScreen"; import TetrisScreen from "../screens/Tetris/TetrisScreen";
import {BlueMindWebsiteScreen} from "../screens/Websites/BlueMindWebsiteScreen";
import LoginScreen from "../screens/Amicale/LoginScreen"; import LoginScreen from "../screens/Amicale/LoginScreen";
import ProfileScreen from "../screens/Amicale/ProfileScreen"; import ProfileScreen from "../screens/Amicale/ProfileScreen";
import ClubListScreen from "../screens/Amicale/Clubs/ClubListScreen"; import ClubListScreen from "../screens/Amicale/Clubs/ClubListScreen";
import ClubAboutScreen from "../screens/Amicale/Clubs/ClubAboutScreen"; import ClubAboutScreen from "../screens/Amicale/Clubs/ClubAboutScreen";
import VoteScreen from "../screens/Amicale/VoteScreen"; import VoteScreen from "../screens/Amicale/VoteScreen";
import AmicaleContactScreen from "../screens/Amicale/AmicaleContactScreen"; import AmicaleContactScreen from "../screens/Amicale/AmicaleContactScreen";
import WebsitesHomeScreen from "../screens/Services/ServicesScreen"; import AmicaleHomeScreen from "../screens/Amicale/AmicaleHomeScreen";
import ServicesSectionScreen from "../screens/Services/ServicesSectionScreen"; import WebsitesHomeScreen from "../screens/Websites/WebsitesHomeScreen";
import InsaHomeScreen from "../screens/Insa/InsaHomeScreen";
const defaultScreenOptions = { const defaultScreenOptions = {
gestureEnabled: true, 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); return createScreenCollapsibleStack(name, Stack, component, title, false);
} }
const ServicesStack = createStackNavigator(); const StudentsStack = createStackNavigator();
function ServicesStackComponent() { function StudentsStackComponent() {
return ( return (
<ServicesStack.Navigator <StudentsStack.Navigator
initialRouteName="index" initialRouteName="index"
headerMode={"screen"} headerMode={"screen"}
screenOptions={defaultScreenOptions} screenOptions={defaultScreenOptions}
> >
{createScreenCollapsibleStack("index", ServicesStack, WebsitesHomeScreen, i18n.t('screens.services'))} <StudentsStack.Screen
{createScreenCollapsibleStack("services-section", ServicesStack, ServicesSectionScreen, "SECTION")} name="index"
component={WebsitesHomeScreen}
{/* INSA */} options={{
{getWebsiteStack("available-rooms", ServicesStack, AvailableRoomScreen, i18n.t('screens.availableRooms'))} title: "WEBSITES HOME",
{getWebsiteStack("bib", ServicesStack, BibScreen, i18n.t('screens.bib'))} }}
{createScreenCollapsibleStack("self-menu", ServicesStack, SelfMenuScreen, i18n.t('screens.menuSelf'))} />
{getWebsiteStack("amicale-website", StudentsStack, AmicaleWebsiteScreen, "Amicale")}
{/* STUDENTS */} {getWebsiteStack("elus-etudiants", StudentsStack, ElusEtudiantsWebsiteScreen, "Élus Étudiants")}
{createScreenCollapsibleStack("proximo", ServicesStack, ProximoMainScreen, i18n.t('screens.proximo'))} {getWebsiteStack("wiketud", StudentsStack, WiketudWebsiteScreen, "Wiketud")}
{getWebsiteStack("tutorinsa", StudentsStack, TutorInsaWebsiteScreen, "Tutor'INSA")}
{createScreenCollapsibleStack("proximo", StudentsStack, ProximoMainScreen, "Proximo")}
{createScreenCollapsibleStack( {createScreenCollapsibleStack(
"proximo-list", "proximo-list",
ServicesStack, StudentsStack,
ProximoListScreen, ProximoListScreen,
i18n.t('screens.proximoArticles'), i18n.t('screens.proximoArticles'),
true, true,
{...screenTransition}, {...screenTransition},
)} )}
<ServicesStack.Screen <StudentsStack.Screen
name="proximo-about" name="proximo-about"
component={ProximoAboutScreen} component={ProximoAboutScreen}
options={{ options={{
@ -117,41 +119,22 @@ function ServicesStackComponent() {
...modalTransition, ...modalTransition,
}} }}
/> />
{getWebsiteStack("amicale-website", ServicesStack, AmicaleWebsiteScreen, i18n.t('screens.amicaleWebsite'))} <StudentsStack.Screen
{getWebsiteStack("elus-etudiants", ServicesStack, ElusEtudiantsWebsiteScreen, "Élus Étudiants")} name="planning"
{getWebsiteStack("wiketud", ServicesStack, WiketudWebsiteScreen, "Wiketud")} component={PlanningScreen}
{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}
options={{ 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, ...modalTransition,
}} }}
/> />
<ServicesStack.Screen </StudentsStack.Navigator>
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>
); );
} }
@ -177,31 +160,26 @@ function ProxiwashStackComponent() {
); );
} }
const PlanningStack = createStackNavigator(); const InsaStack = createStackNavigator();
function PlanningStackComponent() { function InsaStackComponent() {
return ( return (
<PlanningStack.Navigator <InsaStack.Navigator
initialRouteName="index" initialRouteName="index"
headerMode={"screen"} headerMode={"screen"}
screenOptions={defaultScreenOptions} screenOptions={defaultScreenOptions}
> >
<PlanningStack.Screen <InsaStack.Screen
name="planning" name="index"
component={PlanningScreen} component={InsaHomeScreen}
options={{ options={{
title: i18n.t('screens.planning'), title: "INSA HOME",
}} }}
/> />
<PlanningStack.Screen {getWebsiteStack("available-rooms", InsaStack, AvailableRoomScreen, i18n.t('screens.availableRooms'))}
name="planning-information" {getWebsiteStack("bib", InsaStack, BibScreen, i18n.t('screens.bib'))}
component={PlanningDisplayScreen} {createScreenCollapsibleStack("self-menu", InsaStack, SelfMenuScreen, i18n.t('screens.menuSelf'))}
options={{ </InsaStack.Navigator>
title: i18n.t('screens.planningDisplayScreen'),
...modalTransition,
}}
/>
</PlanningStack.Navigator>
); );
} }
@ -235,6 +213,14 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
useNativeDriver: true, useNativeDriver: true,
} }
)} )}
<HomeStack.Screen
name="feed-information"
component={FeedItemScreen}
options={{
title: i18n.t('screens.feedDisplayScreen'),
...modalTransition,
}}
/>
<HomeStack.Screen <HomeStack.Screen
name="scanner" name="scanner"
component={ScannerScreen} component={ScannerScreen}
@ -243,6 +229,36 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
...modalTransition, ...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 <HomeStack.Screen
name="club-information" name="club-information"
component={ClubDisplayScreen} component={ClubDisplayScreen}
@ -252,23 +268,34 @@ function HomeStackComponent(initialRoute: string | null, defaultData: { [key: st
}} }}
/> />
<HomeStack.Screen <HomeStack.Screen
name="feed-information" name="club-about"
component={FeedItemScreen} component={ClubAboutScreen}
options={{ options={{
title: i18n.t('screens.feedDisplayScreen'), title: i18n.t('screens.clubsAbout'),
...modalTransition, ...modalTransition,
}} }}
/> />
<HomeStack.Screen <HomeStack.Screen
name="planning-information" name="vote"
component={PlanningDisplayScreen} component={VoteScreen}
options={{ options={{
title: i18n.t('screens.planningDisplayScreen'), title: i18n.t('screens.vote'),
...modalTransition, }}
/>
<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> </HomeStack.Navigator>
); );
} }
@ -321,26 +348,27 @@ export default class TabNavigator extends React.Component<Props> {
initialRouteName={this.defaultRoute} initialRouteName={this.defaultRoute}
tabBar={props => <CustomTabBar {...props} />} tabBar={props => <CustomTabBar {...props} />}
> >
<Tab.Screen
name="services"
option
component={ServicesStackComponent}
options={{title: i18n.t('screens.services')}}
/>
<Tab.Screen <Tab.Screen
name="proxiwash" name="proxiwash"
component={ProxiwashStackComponent} component={ProxiwashStackComponent}
options={{title: i18n.t('screens.proxiwash')}} options={{title: i18n.t('screens.proxiwash')}}
/> />
<Tab.Screen
name="students"
option
component={StudentsStackComponent}
options={{title: "ETUDIANTS"}}
/>
<Tab.Screen <Tab.Screen
name="home" name="home"
component={this.createHomeStackComponent} component={this.createHomeStackComponent}
options={{title: i18n.t('screens.home')}} options={{title: i18n.t('screens.home')}}
/> />
<Tab.Screen <Tab.Screen
name="planning" name="insa"
component={PlanningStackComponent} component={InsaStackComponent}
options={{title: i18n.t('screens.planning')}} options={{title: "INSA"}}
/> />
<Tab.Screen <Tab.Screen

View file

@ -1,21 +1,16 @@
// @flow // @flow
import * as React from 'react'; 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 {Avatar, Button, Card, HelperText, Paragraph, TextInput, withTheme} from 'react-native-paper';
import ConnectionManager from "../../managers/ConnectionManager"; import ConnectionManager from "../../managers/ConnectionManager";
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import ErrorDialog from "../../components/Dialogs/ErrorDialog"; import ErrorDialog from "../../components/Dialogs/ErrorDialog";
import {withCollapsible} from "../../utils/withCollapsible"; import {CommonActions} from "@react-navigation/native";
import {Collapsible} from "react-navigation-collapsible";
import CustomTabBar from "../../components/Tabbar/CustomTabBar";
import type {CustomTheme} from "../../managers/ThemeManager";
type Props = { type Props = {
navigation: Object, navigation: Object,
route: Object, route: Object,
collapsibleStack: Collapsible,
theme: CustomTheme
} }
type State = { type State = {
@ -46,17 +41,32 @@ class LoginScreen extends React.Component<Props, State> {
dialogError: 0, dialogError: 0,
}; };
colors: Object;
onEmailChange: Function; onEmailChange: Function;
onPasswordChange: Function; onPasswordChange: Function;
passwordInputRef: Object; passwordInputRef: Object;
nextScreen: string;
constructor(props) { constructor(props) {
super(props); super(props);
this.onEmailChange = this.onInputChange.bind(this, true); this.onEmailChange = this.onInputChange.bind(this, true);
this.onPasswordChange = this.onInputChange.bind(this, false); 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) => showErrorDialog = (error: number) =>
this.setState({ this.setState({
dialogVisible: true, dialogVisible: true,
@ -65,7 +75,7 @@ class LoginScreen extends React.Component<Props, State> {
hideErrorDialog = () => this.setState({dialogVisible: false}); hideErrorDialog = () => this.setState({dialogVisible: false});
handleSuccess = () => this.props.navigation.goBack(); handleSuccess = () => this.props.navigation.replace(this.nextScreen);
onResetPasswordClick = () => this.props.navigation.navigate('amicale-website', { onResetPasswordClick = () => this.props.navigation.navigate('amicale-website', {
screen: 'amicale-website', screen: 'amicale-website',
@ -225,7 +235,7 @@ class LoginScreen extends React.Component<Props, State> {
left={(props) => <Avatar.Icon left={(props) => <Avatar.Icon
{...props} {...props}
icon={"help"} icon={"help"}
color={this.props.theme.colors.primary} color={this.colors.primary}
style={{backgroundColor: 'transparent'}}/>} style={{backgroundColor: 'transparent'}}/>}
/> />
<Card.Content> <Card.Content>
@ -238,7 +248,6 @@ class LoginScreen extends React.Component<Props, State> {
} }
render() { render() {
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
return ( return (
<KeyboardAvoidingView <KeyboardAvoidingView
behavior={"height"} behavior={"height"}
@ -247,14 +256,7 @@ class LoginScreen extends React.Component<Props, State> {
enabled enabled
keyboardVerticalOffset={100} keyboardVerticalOffset={100}
> >
<Animated.ScrollView <ScrollView>
onScroll={onScroll}
contentContainerStyle={{
paddingTop: containerPaddingTop,
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT + 20
}}
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
>
<View> <View>
{this.getMainCard()} {this.getMainCard()}
{this.getSecondaryCard()} {this.getSecondaryCard()}
@ -264,7 +266,7 @@ class LoginScreen extends React.Component<Props, State> {
onDismiss={this.hideErrorDialog} onDismiss={this.hideErrorDialog}
errorCode={this.state.dialogError} errorCode={this.state.dialogError}
/> />
</Animated.ScrollView> </ScrollView>
</KeyboardAvoidingView> </KeyboardAvoidingView>
); );
} }
@ -290,4 +292,4 @@ const styles = StyleSheet.create({
} }
}); });
export default withCollapsible(withTheme(LoginScreen)); export default withTheme(LoginScreen);

View file

@ -1,20 +1,16 @@
// @flow // @flow
import * as React from 'react'; 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 {Avatar, Button, Card, Divider, List, withTheme} from 'react-native-paper';
import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen"; import AuthenticatedScreen from "../../components/Amicale/AuthenticatedScreen";
import i18n from 'i18n-js'; import i18n from 'i18n-js';
import LogoutDialog from "../../components/Amicale/LogoutDialog"; import LogoutDialog from "../../components/Amicale/LogoutDialog";
import MaterialHeaderButtons, {Item} from "../../components/Overrides/CustomHeaderButton"; 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 = { type Props = {
navigation: Object, navigation: Object,
theme: Object, theme: Object,
collapsibleStack: Collapsible,
} }
type State = { type State = {
@ -56,20 +52,12 @@ class ProfileScreen extends React.Component<Props, State> {
getScreen = (data: Object) => { getScreen = (data: Object) => {
this.data = data[0]; this.data = data[0];
const {containerPaddingTop, scrollIndicatorInsetTop, onScroll} = this.props.collapsibleStack;
return ( return (
<View style={{flex: 1}}> <View>
<Animated.FlatList {/*$FlowFixMe*/}
<FlatList
renderItem={this.getRenderItem} renderItem={this.getRenderItem}
data={this.flatListData} data={this.flatListData}
// Animations
onScroll={onScroll}
contentContainerStyle={{
paddingTop: containerPaddingTop,
paddingBottom: CustomTabBar.TAB_BAR_HEIGHT,
minHeight: '100%'
}}
scrollIndicatorInsets={{top: scrollIndicatorInsetTop}}
/> />
<LogoutDialog <LogoutDialog
{...this.props} {...this.props}
@ -335,4 +323,4 @@ const styles = StyleSheet.create({
}); });
export default withCollapsible(withTheme(ProfileScreen)); export default withTheme(ProfileScreen);

View file

@ -17,9 +17,6 @@ import AnimatedFAB from "../../components/Animations/AnimatedFAB";
import {StackNavigationProp} from "@react-navigation/stack"; import {StackNavigationProp} from "@react-navigation/stack";
import type {CustomTheme} from "../../managers/ThemeManager"; import type {CustomTheme} from "../../managers/ThemeManager";
import {View} from "react-native-animatable"; 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"; // import DATA from "../dashboard_data.json";
@ -98,32 +95,21 @@ type Props = {
theme: CustomTheme, theme: CustomTheme,
} }
type State = {
dialogVisible: boolean,
}
/** /**
* Class defining the app's home screen * Class defining the app's home screen
*/ */
class HomeScreen extends React.Component<Props, State> { class HomeScreen extends React.Component<Props> {
colors: Object; colors: Object;
isLoggedIn: boolean | null;
fabRef: { current: null | AnimatedFAB }; fabRef: { current: null | AnimatedFAB };
currentNewFeed: Array<feedItem>; currentNewFeed: Array<feedItem>;
state = {
dialogVisible: false,
}
constructor(props) { constructor(props) {
super(props); super(props);
this.colors = props.theme.colors; this.colors = props.theme.colors;
this.fabRef = React.createRef(); this.fabRef = React.createRef();
this.currentNewFeed = []; this.currentNewFeed = [];
this.isLoggedIn = null;
} }
/** /**
@ -144,12 +130,9 @@ class HomeScreen extends React.Component<Props, State> {
} }
onScreenFocus = () => { onScreenFocus = () => {
if (ConnectionManager.getInstance().isLoggedIn() !== this.isLoggedIn) { this.props.navigation.setOptions({
this.isLoggedIn = ConnectionManager.getInstance().isLoggedIn(); headerRight: this.getHeaderButton,
this.props.navigation.setOptions({ });
headerRight: this.getHeaderButton,
});
}
// handle link open when home is not focused or created // handle link open when home is not focused or created
this.handleNavigationParams(); this.handleNavigationParams();
}; };
@ -165,43 +148,25 @@ class HomeScreen extends React.Component<Props, State> {
}; };
getHeaderButton = () => { 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 onPressSettings = () => this.props.navigation.navigate("settings");
const onPressAbout = () => this.props.navigation.navigate("about"); const onPressAbout = () => this.props.navigation.navigate("about");
return <MaterialHeaderButtons> return <MaterialHeaderButtons>
<Item title="log" iconName={logIcon} color={logColor} onPress={onPressLog}/> <Item title="settings" iconName={"settings"} onPress={onPressSettings}/>
<HiddenItem title={i18n.t("screens.settings")} iconName={"settings"} onPress={onPressSettings}/> <Item title="information" iconName={"information"} onPress={onPressAbout}/>
<HiddenItem title={i18n.t("screens.about")} iconName={"information"} onPress={onPressAbout}/>
</MaterialHeaderButtons>; </MaterialHeaderButtons>;
}; };
showDisconnectDialog = () => this.setState({dialogVisible: true});
hideDisconnectDialog = () => this.setState({dialogVisible: false});
onProxiwashClick = () => { onProxiwashClick = () => {
this.props.navigation.navigate("proxiwash"); this.props.navigation.navigate("proxiwash");
}; };
onProximoClick = () => { onProximoClick = () => {
this.props.navigation.navigate('services', {screen: "index"}); this.props.navigation.navigate("proximo");
}; };
onTutorInsaClick = () => { onTutorInsaClick = () => this.props.navigation.navigate('tutorinsa');
this.props.navigation.navigate('services', {screen: "index"});
};
onMenuClick = () => { onMenuClick = () => this.props.navigation.navigate('self-menu');
this.props.navigation.navigate('self-menu');
};
/** /**
* Creates the dataset to be used in the FlatList * Creates the dataset to be used in the FlatList
@ -279,7 +244,7 @@ class HomeScreen extends React.Component<Props, State> {
}, },
{ {
id: 'today_menu', id: 'today_menu',
data: dashboardData == null ? [] : dashboardData.today_menu, data: dashboardData == null ? 0 : dashboardData.today_menu,
icon: 'silverware-fork-knife', icon: 'silverware-fork-knife',
color: this.colors.menuColor, color: this.colors.menuColor,
onPress: this.onMenuClick, onPress: this.onMenuClick,
@ -312,7 +277,7 @@ class HomeScreen extends React.Component<Props, State> {
} }
getDashboardActions() { 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>) { getDashboardEvent(content: Array<event>) {
let futureEvents = this.getFutureEvents(content); let futureEvents = this.getFutureEvents(content);
let displayEvent = this.getDisplayEvent(futureEvents); let displayEvent = this.getDisplayEvent(futureEvents);
// const clickPreviewAction = () => const clickPreviewAction = () =>
// this.props.navigation.navigate('students', { this.props.navigation.navigate('home-planning-information', {data: displayEvent});
// screen: 'planning-information',
// params: {data: displayEvent}
// });
return ( return (
<DashboardItem <DashboardItem
eventNumber={futureEvents.length} eventNumber={futureEvents.length}
@ -454,7 +416,7 @@ class HomeScreen extends React.Component<Props, State> {
> >
<PreviewEventDashboardItem <PreviewEventDashboardItem
event={displayEvent != null ? displayEvent : undefined} event={displayEvent != null ? displayEvent : undefined}
clickAction={this.onEventContainerClick} clickAction={clickPreviewAction}
/> />
</DashboardItem> </DashboardItem>
); );
@ -560,11 +522,6 @@ class HomeScreen extends React.Component<Props, State> {
icon="qrcode-scan" icon="qrcode-scan"
onPress={this.openScanner} onPress={this.openScanner}
/> />
<LogoutDialog
{...this.props}
visible={this.state.dialogVisible}
onDismiss={this.hideDisconnectDialog}
/>
</View> </View>
); );
} }

View 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);

View file

@ -10,8 +10,6 @@ type Props = {
navigation: Object, navigation: Object,
}; };
const LOGO = "https://etud.insa-toulouse.fr/~amicale_app/images/proximo-logo.png";
/** /**
* Class defining the proximo about screen. * Class defining the proximo about screen.
*/ */
@ -29,8 +27,9 @@ export default class ProximoAboutScreen extends React.Component<Props> {
alignItems: 'center' alignItems: 'center'
}}> }}>
<Image <Image
source={{uri: LOGO}} source={require('../../../assets/proximo-logo.png')}
style={{height: '100%', width: '100%', resizeMode: "contain"}}/> style={{flex: 1, resizeMode: "contain"}}
resizeMode="contain"/>
</View> </View>
<Text>{i18n.t('proximoScreen.description')}</Text> <Text>{i18n.t('proximoScreen.description')}</Text>
<Card style={{margin: 5}}> <Card style={{margin: 5}}>

View file

@ -10,8 +10,6 @@ type Props = {
navigation: Object, navigation: Object,
}; };
const LOGO = "https://etud.insa-toulouse.fr/~amicale_app/images/proxiwash-logo.png";
/** /**
* Class defining the proxiwash about screen. * Class defining the proxiwash about screen.
*/ */
@ -29,8 +27,9 @@ export default class ProxiwashAboutScreen extends React.Component<Props> {
alignItems: 'center' alignItems: 'center'
}}> }}>
<Image <Image
source={{uri: LOGO}} source={require('../../../assets/proxiwash-logo.png')}
style={{height: '100%', width: '100%', resizeMode: "contain"}}/> style={{flex: 1, resizeMode: "contain"}}
resizeMode="contain"/>
</View> </View>
<Text>{i18n.t('proxiwashScreen.description')}</Text> <Text>{i18n.t('proxiwashScreen.description')}</Text>
<Card style={{margin: 5}}> <Card style={{margin: 5}}>

View file

@ -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));

View file

@ -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);

View file

@ -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}/>
);
};

View file

@ -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}/>
);
};

View 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);

View file

@ -1,15 +1,13 @@
{ {
"screens": { "screens": {
"home": "Home", "home": "Home",
"planning": "Events", "planning": "Planning",
"planningDisplayScreen": "Event details", "planningDisplayScreen": "Event details",
"clubDisplayScreen": "Club details", "clubDisplayScreen": "Club details",
"feedDisplayScreen": "Details", "feedDisplayScreen": "Details",
"clubsAbout": "Clubs", "clubsAbout": "Clubs",
"amicaleAbout": "Contact", "amicaleAbout": "The Amicale",
"amicaleWebsite": "Amicale's website",
"proxiwash": "Proxiwash", "proxiwash": "Proxiwash",
"services": "Services",
"proximo": "Proximo", "proximo": "Proximo",
"proximoArticles": "Articles", "proximoArticles": "Articles",
"menuSelf": "RU Menu", "menuSelf": "RU Menu",
@ -97,11 +95,28 @@
"todayEventsSubtitleNA": "No events today", "todayEventsSubtitleNA": "No events today",
"todayEventsSubtitle": " event coming today", "todayEventsSubtitle": " event coming today",
"todayEventsSubtitlePlural": " events coming today", "todayEventsSubtitlePlural": " events coming today",
"amicaleTitle": "The Amicale", "proximoTitle": "Proximo",
"amicaleConnect": "Login", "proximoSubtitleNA": "No articles available",
"amicaleConnected": "See available services" "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": { "aboutScreen": {
"appstore": "See on the Appstore", "appstore": "See on the Appstore",
"playstore": "See on the Playstore", "playstore": "See on the Playstore",
@ -278,7 +293,7 @@
"animation": "Animation", "animation": "Animation",
"clubs": "Clubs", "clubs": "Clubs",
"event": "Events", "event": "Events",
"tech": "Technique", "tech" : "Technique",
"communication": "Communication", "communication": "Communication",
"intraSchools": "Alumni / IAT", "intraSchools": "Alumni / IAT",
"publicRelations": "Public Relations" "publicRelations": "Public Relations"
@ -296,28 +311,28 @@
"tease": { "tease": {
"title": "Elections incoming", "title": "Elections incoming",
"subtitle": "Be ready to vote!", "subtitle": "Be ready to vote!",
"message": "Vote start:" "message" : "Vote start:"
}, },
"wait": { "wait": {
"titleSubmitted": "Vote submitted!", "titleSubmitted": "Vote submitted!",
"titleEnded": "Votes closed", "titleEnded": "Votes closed",
"subtitle": "Waiting for results...", "subtitle" : "Waiting for results...",
"messageSubmitted": "Vote submitted successfully.", "messageSubmitted" : "Vote submitted successfully.",
"messageVoted": "Thank you for your participation.", "messageVoted" : "Thank you for your participation.",
"messageDate": "Results available:", "messageDate" : "Results available:",
"messageDateUndefined": "Results will be available shortly" "messageDateUndefined" : "Results will be available shortly"
}, },
"results": { "results": {
"title": "Results", "title": "Results",
"subtitle": "Available until:", "subtitle": "Available until:",
"totalVotes": "Total votes:", "totalVotes" : "Total votes:",
"votes": "votes" "votes" : "votes"
}, },
"title": { "title": {
"title": "The Elections", "title": "The Elections",
"subtitle": "Why your vote is important", "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", "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" "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": { "dialog": {
@ -382,11 +397,5 @@
"time": "Time: ", "time": "Time: ",
"exit": "leave Game" "exit": "leave Game"
} }
},
"servicesScreen": {
"amicale": "The Amicale",
"students": "Student services",
"insa": "INSA services",
"notLoggedIn": "Not logged in"
} }
} }

View file

@ -1,15 +1,13 @@
{ {
"screens": { "screens": {
"home": "Accueil", "home": "Accueil",
"planning": "Événements", "planning": "Planning",
"planningDisplayScreen": "Détails", "planningDisplayScreen": "Détails",
"clubDisplayScreen": "Détails", "clubDisplayScreen": "Détails",
"feedDisplayScreen": "Détails", "feedDisplayScreen": "Détails",
"clubsAbout": "Les Clubs", "clubsAbout": "Les Clubs",
"amicaleAbout": "Contact", "amicaleAbout": "L' Amicale",
"amicaleWebsite": "Site de l'Amicale",
"proxiwash": "Proxiwash", "proxiwash": "Proxiwash",
"services": "Services",
"proximo": "Proximo", "proximo": "Proximo",
"proximoArticles": "Articles", "proximoArticles": "Articles",
"menuSelf": "Menu du RU", "menuSelf": "Menu du RU",
@ -97,11 +95,28 @@
"todayEventsSubtitleNA": "Pas d'événement", "todayEventsSubtitleNA": "Pas d'événement",
"todayEventsSubtitle": " événement aujourd'hui", "todayEventsSubtitle": " événement aujourd'hui",
"todayEventsSubtitlePlural": " événements aujourd'hui", "todayEventsSubtitlePlural": " événements aujourd'hui",
"amicaleTitle": "L'Amicale", "proximoTitle": "Proximo",
"amicaleConnect": "Se connecter", "proximoSubtitleNA": "pas d'article en vente",
"amicaleConnected": "Voir les services disponibles" "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": { "aboutScreen": {
"appstore": "Voir sur l'Appstore", "appstore": "Voir sur l'Appstore",
"playstore": "Voir sur le Playstore", "playstore": "Voir sur le Playstore",
@ -278,7 +293,7 @@
"animation": "Animation", "animation": "Animation",
"clubs": "Clubs", "clubs": "Clubs",
"event": "Événements", "event": "Événements",
"tech": "Technique", "tech" : "Technique",
"communication": "Communication", "communication": "Communication",
"intraSchools": "Alumni / IAT", "intraSchools": "Alumni / IAT",
"publicRelations": "Relations Publiques" "publicRelations": "Relations Publiques"
@ -296,28 +311,28 @@
"tease": { "tease": {
"title": "Les élections arrivent", "title": "Les élections arrivent",
"subtitle": "Préparez vous à voter !", "subtitle": "Préparez vous à voter !",
"message": "Début des votes :" "message" : "Début des votes :"
}, },
"wait": { "wait": {
"titleSubmitted": "Vote envoyé !", "titleSubmitted": "Vote envoyé !",
"titleEnded": "Votes fermés", "titleEnded": "Votes fermés",
"subtitle": "Attente des résultats...", "subtitle" : "Attente des résultats...",
"messageSubmitted": "Votre vote a bien été envoyé.", "messageSubmitted" : "Votre vote a bien été envoyé.",
"messageVoted": "Merci pour votre participation.", "messageVoted" : "Merci pour votre participation.",
"messageDate": "Disponibilité des résultats :", "messageDate" : "Disponibilité des résultats :",
"messageDateUndefined": "les résultats seront disponibles sous peu." "messageDateUndefined" : "les résultats seront disponibles sous peu."
}, },
"results": { "results": {
"title": "Résultats", "title": "Résultats",
"subtitle": "Disponibles jusqu'à :", "subtitle": "Disponibles jusqu'à :",
"totalVotes": "Nombre total de votes :", "totalVotes" : "Nombre total de votes :",
"votes": "votes" "votes" : "votes"
}, },
"title": { "title": {
"title": "Les Élections", "title": "Les Élections",
"subtitle": "Pourquoi votre vote est important", "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 à ladministration pour que la vie de campus soit des plus riches !\nAlors à vous de jouer ! \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 à ladministration 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 à ladministration que les INSAiens la soutiennent ! Ça compte toujours pour les décisions difficiles ! \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 à ladministration que les INSAiens la soutiennent ! Ça compte toujours pour les décisions difficiles ! \uD83D\uDE09"
} }
}, },
"dialog": { "dialog": {
@ -382,11 +397,5 @@
"time": "Temps: ", "time": "Temps: ",
"exit": "Quitter" "exit": "Quitter"
} }
},
"servicesScreen": {
"amicale": "L'Amicale",
"students": "Services étudiants",
"insa": "Services de l'INSA",
"notLoggedIn": "Non connecté"
} }
} }