Compare commits
2 commits
ac19b77fd3
...
b405f2aa6b
| Author | SHA1 | Date | |
|---|---|---|---|
| b405f2aa6b | |||
| 2022b738f5 |
15 changed files with 683 additions and 194 deletions
|
|
@ -6,7 +6,8 @@
|
||||||
"categories": {
|
"categories": {
|
||||||
"amicale": "The Amicale",
|
"amicale": "The Amicale",
|
||||||
"students": "Student services",
|
"students": "Student services",
|
||||||
"insa": "INSA services"
|
"insa": "INSA services",
|
||||||
|
"special": "Proxiwash"
|
||||||
},
|
},
|
||||||
"descriptions": {
|
"descriptions": {
|
||||||
"clubs": "See info about your favorite club and discover new ones",
|
"clubs": "See info about your favorite club and discover new ones",
|
||||||
|
|
@ -23,7 +24,9 @@
|
||||||
"mails": "Check your INSA mails",
|
"mails": "Check your INSA mails",
|
||||||
"ent": "See your grades",
|
"ent": "See your grades",
|
||||||
"insaAccount": "See your information and change your password",
|
"insaAccount": "See your information and change your password",
|
||||||
"equipment": "Book a BBQ or other equipment"
|
"equipment": "Book a BBQ or other equipment",
|
||||||
|
"washers": "Number of available washers",
|
||||||
|
"dryers": "Number of available dryers"
|
||||||
},
|
},
|
||||||
"mascotDialog": {
|
"mascotDialog": {
|
||||||
"title": "So handy!",
|
"title": "So handy!",
|
||||||
|
|
@ -320,9 +323,16 @@
|
||||||
"nightModeAutoSub": "Follows the mode chosen by your system",
|
"nightModeAutoSub": "Follows the mode chosen by your system",
|
||||||
"startScreen": "Start Screen",
|
"startScreen": "Start Screen",
|
||||||
"startScreenSub": "Select which screen to start the app on",
|
"startScreenSub": "Select which screen to start the app on",
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"dashboardSub": "Edit what services to display on the dashboard",
|
||||||
"proxiwashNotifReminder": "Machine running reminder",
|
"proxiwashNotifReminder": "Machine running reminder",
|
||||||
"proxiwashNotifReminderSub": "How many minutes before",
|
"proxiwashNotifReminderSub": "How many minutes before",
|
||||||
"information": "Information"
|
"information": "Information",
|
||||||
|
"dashboardEdit": {
|
||||||
|
"title": "Edit dashboard",
|
||||||
|
"message": "The five items above represent your dashboard.\nYou can replace one of its services by selecting it, and then by clicking on the desired new service in the list bellow.",
|
||||||
|
"undo": "Undo changes"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "About",
|
"title": "About",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
"categories": {
|
"categories": {
|
||||||
"amicale": "L' Amicale",
|
"amicale": "L' Amicale",
|
||||||
"students": "Services étudiants",
|
"students": "Services étudiants",
|
||||||
"insa": "Services de l'INSA"
|
"insa": "Services de l'INSA",
|
||||||
|
"special": "Proxiwash"
|
||||||
},
|
},
|
||||||
"descriptions": {
|
"descriptions": {
|
||||||
"clubs": "Tous les clubs et leurs infos",
|
"clubs": "Tous les clubs et leurs infos",
|
||||||
|
|
@ -23,7 +24,9 @@
|
||||||
"mails": "Vérifie tes mails INSA",
|
"mails": "Vérifie tes mails INSA",
|
||||||
"ent": "Retrouve tes notes",
|
"ent": "Retrouve tes notes",
|
||||||
"insaAccount": "Accède à tes infos INSA et modifie ton mot de passe",
|
"insaAccount": "Accède à tes infos INSA et modifie ton mot de passe",
|
||||||
"equipment": "Réserve un BBQ ou autre matériel"
|
"equipment": "Réserve un BBQ ou autre matériel",
|
||||||
|
"washers": "Nombre de lave-Linges disponibles",
|
||||||
|
"dryers": "Nombre de sèche-Linges disponibles"
|
||||||
},
|
},
|
||||||
"mascotDialog": {
|
"mascotDialog": {
|
||||||
"title": "Un peu perdu ?",
|
"title": "Un peu perdu ?",
|
||||||
|
|
@ -319,9 +322,16 @@
|
||||||
"nightModeAutoSub": "Suit le mode sélectionné par le système",
|
"nightModeAutoSub": "Suit le mode sélectionné par le système",
|
||||||
"startScreen": "Écran de démarrage",
|
"startScreen": "Écran de démarrage",
|
||||||
"startScreenSub": "Choisis l'écran sur lequel démarre Campus",
|
"startScreenSub": "Choisis l'écran sur lequel démarre Campus",
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"dashboardSub": "Choisis les services à afficher sur la dashboard",
|
||||||
"proxiwashNotifReminder": "Rappel de machine en cours",
|
"proxiwashNotifReminder": "Rappel de machine en cours",
|
||||||
"proxiwashNotifReminderSub": "Combien de minutes avant",
|
"proxiwashNotifReminderSub": "Combien de minutes avant",
|
||||||
"information": "Informations"
|
"information": "Informations",
|
||||||
|
"dashboardEdit": {
|
||||||
|
"title": "Modifier la dashboard",
|
||||||
|
"message": "Les 5 icones ci-dessus représentent ta dashboard.\nTu peux remplacer un de ses services en cliquant dessus, puis en sélectionnant le nouveau service de ton choix dans la liste ci-dessous.",
|
||||||
|
"undo": "Annuler les changements"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"title": "À Propos",
|
"title": "À Propos",
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Badge, IconButton, withTheme} from 'react-native-paper';
|
import {Badge, TouchableRipple, withTheme} from 'react-native-paper';
|
||||||
import {View} from "react-native";
|
import {Dimensions, Image, View} from "react-native";
|
||||||
import type {CustomTheme} from "../../managers/ThemeManager";
|
import type {CustomTheme} from "../../managers/ThemeManager";
|
||||||
import * as Animatable from "react-native-animatable";
|
import * as Animatable from "react-native-animatable";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
color: string,
|
image: string,
|
||||||
icon: string,
|
onPress: () => void,
|
||||||
clickAction: () => void,
|
badgeCount: number | null,
|
||||||
isAvailable: boolean,
|
|
||||||
badgeNumber: number,
|
|
||||||
theme: CustomTheme,
|
theme: CustomTheme,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -22,42 +20,60 @@ const AnimatableBadge = Animatable.createAnimatableComponent(Badge);
|
||||||
*/
|
*/
|
||||||
class SmallDashboardItem extends React.Component<Props> {
|
class SmallDashboardItem extends React.Component<Props> {
|
||||||
|
|
||||||
|
itemSize: number;
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.itemSize = Dimensions.get('window').width / 8;
|
||||||
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: Props) {
|
shouldComponentUpdate(nextProps: Props) {
|
||||||
return (nextProps.theme.dark !== this.props.theme.dark)
|
return (nextProps.theme.dark !== this.props.theme.dark)
|
||||||
|| (nextProps.isAvailable !== this.props.isAvailable)
|
|| (nextProps.badgeCount !== this.props.badgeCount);
|
||||||
|| (nextProps.badgeNumber !== this.props.badgeNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
const colors = props.theme.colors;
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<TouchableRipple
|
||||||
<IconButton
|
onPress={this.props.onPress}
|
||||||
icon={props.icon}
|
borderless={true}
|
||||||
color={
|
style={{
|
||||||
props.isAvailable
|
marginLeft: 5,
|
||||||
? props.color
|
marginRight: 5,
|
||||||
: colors.textDisabled
|
}}
|
||||||
}
|
>
|
||||||
size={35}
|
<View style={{
|
||||||
onPress={props.clickAction}
|
width: this.itemSize,
|
||||||
/>
|
height: this.itemSize,
|
||||||
{
|
}}>
|
||||||
props.badgeNumber > 0 ?
|
<Image
|
||||||
<AnimatableBadge
|
source={{uri: props.image}}
|
||||||
animation={"zoomIn"}
|
|
||||||
duration={300}
|
|
||||||
useNativeDriver
|
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
width: "100%",
|
||||||
top: 5,
|
height: "100%",
|
||||||
right: 5
|
}}
|
||||||
}}>
|
/>
|
||||||
{props.badgeNumber}
|
{
|
||||||
</AnimatableBadge> : null
|
props.badgeCount != null && props.badgeCount > 0 ?
|
||||||
}
|
<AnimatableBadge
|
||||||
</View>
|
animation={"zoomIn"}
|
||||||
|
duration={300}
|
||||||
|
useNativeDriver
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
backgroundColor: props.theme.colors.primary,
|
||||||
|
borderColor: "#fff",
|
||||||
|
borderWidth: 1,
|
||||||
|
}}>
|
||||||
|
{props.badgeCount}
|
||||||
|
</AnimatableBadge> : null
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
</TouchableRipple>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
72
src/components/Lists/DashboardEdit/DashboardEditAccordion.js
Normal file
72
src/components/Lists/DashboardEdit/DashboardEditAccordion.js
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import {withTheme} from 'react-native-paper';
|
||||||
|
import {FlatList, Image, View} from "react-native";
|
||||||
|
import DashboardEditItem from "./DashboardEditItem";
|
||||||
|
import AnimatedAccordion from "../../Animations/AnimatedAccordion";
|
||||||
|
import type {ServiceCategory, ServiceItem} from "../../../managers/ServicesManager";
|
||||||
|
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
|
import type {CustomTheme} from "../../../managers/ThemeManager";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
item: ServiceCategory,
|
||||||
|
activeDashboard: Array<string>,
|
||||||
|
onPress: (service: ServiceItem) => void,
|
||||||
|
theme: CustomTheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
const LIST_ITEM_HEIGHT = 64;
|
||||||
|
|
||||||
|
class DashboardEditAccordion extends React.Component<Props> {
|
||||||
|
|
||||||
|
renderItem = ({item}: { item: ServiceItem }) => {
|
||||||
|
return (
|
||||||
|
<DashboardEditItem
|
||||||
|
height={LIST_ITEM_HEIGHT}
|
||||||
|
item={item}
|
||||||
|
isActive={this.props.activeDashboard.includes(item.key)}
|
||||||
|
onPress={() => this.props.onPress(item)}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemLayout = (data, index) => ({length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index});
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const item = this.props.item;
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<AnimatedAccordion
|
||||||
|
title={item.title}
|
||||||
|
left={props => typeof item.image === "number"
|
||||||
|
? <Image
|
||||||
|
{...props}
|
||||||
|
source={item.image}
|
||||||
|
style={{
|
||||||
|
width: 40,
|
||||||
|
height: 40
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
: <MaterialCommunityIcons
|
||||||
|
//$FlowFixMe
|
||||||
|
name={item.image}
|
||||||
|
color={this.props.theme.colors.primary}
|
||||||
|
size={40}/>}
|
||||||
|
>
|
||||||
|
{/*$FlowFixMe*/}
|
||||||
|
<FlatList
|
||||||
|
data={item.content}
|
||||||
|
extraData={this.props.activeDashboard.toString()}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
listKey={item.key}
|
||||||
|
// Performance props, see https://reactnative.dev/docs/optimizing-flatlist-configuration
|
||||||
|
getItemLayout={this.itemLayout}
|
||||||
|
removeClippedSubviews={true}
|
||||||
|
/>
|
||||||
|
</AnimatedAccordion>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme(DashboardEditAccordion)
|
||||||
55
src/components/Lists/DashboardEdit/DashboardEditItem.js
Normal file
55
src/components/Lists/DashboardEdit/DashboardEditItem.js
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import {Image} from "react-native";
|
||||||
|
import {List, withTheme} from 'react-native-paper';
|
||||||
|
import type {CustomTheme} from "../../../managers/ThemeManager";
|
||||||
|
import type {ServiceItem} from "../../../managers/ServicesManager";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
item: ServiceItem,
|
||||||
|
isActive: boolean,
|
||||||
|
height: number,
|
||||||
|
onPress: () => void,
|
||||||
|
theme: CustomTheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
class DashboardEditItem extends React.Component<Props> {
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps: Props) {
|
||||||
|
return (nextProps.isActive !== this.props.isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<List.Item
|
||||||
|
title={this.props.item.title}
|
||||||
|
description={this.props.item.subtitle}
|
||||||
|
onPress={this.props.isActive ? null : this.props.onPress}
|
||||||
|
left={props =>
|
||||||
|
<Image
|
||||||
|
{...props}
|
||||||
|
source={{uri: this.props.item.image}}
|
||||||
|
style={{
|
||||||
|
width: 40,
|
||||||
|
height: 40
|
||||||
|
}}
|
||||||
|
/>}
|
||||||
|
right={props => this.props.isActive
|
||||||
|
? <List.Icon
|
||||||
|
{...props}
|
||||||
|
icon={"check"}
|
||||||
|
color={this.props.theme.colors.success}
|
||||||
|
/> : null}
|
||||||
|
style={{
|
||||||
|
height: this.props.height,
|
||||||
|
justifyContent: 'center',
|
||||||
|
paddingLeft: 30,
|
||||||
|
backgroundColor: this.props.isActive ? this.props.theme.colors.proxiwashFinishedColor : "transparent"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme(DashboardEditItem);
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import {TouchableRipple, withTheme} from 'react-native-paper';
|
||||||
|
import {Dimensions, Image, View} from "react-native";
|
||||||
|
import type {CustomTheme} from "../../../managers/ThemeManager";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
image: string,
|
||||||
|
isActive: boolean,
|
||||||
|
onPress: () => void,
|
||||||
|
theme: CustomTheme,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component used to render a small dashboard item
|
||||||
|
*/
|
||||||
|
class DashboardEditPreviewItem extends React.Component<Props> {
|
||||||
|
|
||||||
|
itemSize: number;
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.itemSize = Dimensions.get('window').width / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const props = this.props;
|
||||||
|
return (
|
||||||
|
<TouchableRipple
|
||||||
|
onPress={this.props.onPress}
|
||||||
|
borderless={true}
|
||||||
|
style={{
|
||||||
|
marginLeft: 5,
|
||||||
|
marginRight: 5,
|
||||||
|
backgroundColor: this.props.isActive ? this.props.theme.colors.textDisabled : "transparent",
|
||||||
|
borderRadius: 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{
|
||||||
|
width: this.itemSize,
|
||||||
|
height: this.itemSize,
|
||||||
|
}}>
|
||||||
|
<Image
|
||||||
|
source={{uri: props.image}}
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</TouchableRipple>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme(DashboardEditPreviewItem)
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
import {SERVICES_KEY} from "./ServicesManager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton used to manage preferences.
|
* Singleton used to manage preferences.
|
||||||
|
|
@ -119,6 +120,17 @@ export default class AsyncStorageManager {
|
||||||
default: '[]',
|
default: '[]',
|
||||||
current: '',
|
current: '',
|
||||||
},
|
},
|
||||||
|
dashboardItems: {
|
||||||
|
key: 'dashboardItems',
|
||||||
|
default: JSON.stringify([
|
||||||
|
SERVICES_KEY.EMAIL,
|
||||||
|
SERVICES_KEY.WASHERS,
|
||||||
|
SERVICES_KEY.PROXIMO,
|
||||||
|
SERVICES_KEY.TUTOR_INSA,
|
||||||
|
SERVICES_KEY.RU,
|
||||||
|
]),
|
||||||
|
current: '',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
26
src/managers/DashboardManager.js
Normal file
26
src/managers/DashboardManager.js
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import type {ServiceItem} from "./ServicesManager";
|
||||||
|
import ServicesManager from "./ServicesManager";
|
||||||
|
import {StackNavigationProp} from "@react-navigation/stack";
|
||||||
|
import {getSublistWithIds} from "../utils/Utils";
|
||||||
|
import AsyncStorageManager from "./AsyncStorageManager";
|
||||||
|
|
||||||
|
|
||||||
|
export default class DashboardManager extends ServicesManager{
|
||||||
|
|
||||||
|
constructor(nav: StackNavigationProp) {
|
||||||
|
super(nav)
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentDashboard(): Array<ServiceItem> {
|
||||||
|
const dashboardIdList = JSON.parse(AsyncStorageManager.getInstance().preferences.dashboardItems.current);
|
||||||
|
const allDatasets = [
|
||||||
|
...this.amicaleDataset,
|
||||||
|
...this.studentsDataset,
|
||||||
|
...this.insaDataset,
|
||||||
|
...this.specialDataset,
|
||||||
|
];
|
||||||
|
return getSublistWithIds(dashboardIdList, allDatasets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +1,25 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import type {cardList} from "../components/Lists/CardList/CardList";
|
|
||||||
import i18n from "i18n-js";
|
import i18n from "i18n-js";
|
||||||
import AvailableWebsites from "../constants/AvailableWebsites";
|
import AvailableWebsites from "../constants/AvailableWebsites";
|
||||||
import {StackNavigationProp} from "@react-navigation/stack";
|
import {StackNavigationProp} from "@react-navigation/stack";
|
||||||
import ConnectionManager from "./ConnectionManager";
|
import ConnectionManager from "./ConnectionManager";
|
||||||
|
import type {fullDashboard} from "../screens/Home/HomeScreen";
|
||||||
|
|
||||||
|
// AMICALE
|
||||||
const CLUBS_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Clubs.png";
|
const CLUBS_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Clubs.png";
|
||||||
const PROFILE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ProfilAmicaliste.png";
|
const PROFILE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ProfilAmicaliste.png";
|
||||||
const EQUIPMENT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Materiel.png";
|
const EQUIPMENT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Materiel.png";
|
||||||
const VOTE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Vote.png";
|
const VOTE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Vote.png";
|
||||||
const AMICALE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/WebsiteAmicale.png";
|
const AMICALE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/WebsiteAmicale.png";
|
||||||
|
|
||||||
|
// STUDENTS
|
||||||
const PROXIMO_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Proximo.png"
|
const PROXIMO_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Proximo.png"
|
||||||
const WIKETUD_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Wiketud.png";
|
const WIKETUD_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Wiketud.png";
|
||||||
const EE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/EEC.png";
|
const EE_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/EEC.png";
|
||||||
const TUTORINSA_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/TutorINSA.png";
|
const TUTORINSA_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/TutorINSA.png";
|
||||||
|
|
||||||
|
// INSA
|
||||||
const BIB_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Bib.png";
|
const BIB_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Bib.png";
|
||||||
const RU_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/RU.png";
|
const RU_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/RU.png";
|
||||||
const ROOM_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Salles.png";
|
const ROOM_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Salles.png";
|
||||||
|
|
@ -24,9 +27,15 @@ const EMAIL_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Bluemind.
|
||||||
const ENT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ENT.png";
|
const ENT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ENT.png";
|
||||||
const ACCOUNT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Account.png";
|
const ACCOUNT_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/Account.png";
|
||||||
|
|
||||||
|
// SPECIAL
|
||||||
|
const WASHER_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ProxiwashLaveLinge.png";
|
||||||
|
const DRYER_IMAGE = "https://etud.insa-toulouse.fr/~amicale_app/images/ProxiwashSecheLinge.png";
|
||||||
|
|
||||||
|
const AMICALE_LOGO = require("../../assets/amicale.png");
|
||||||
|
|
||||||
export const SERVICES_KEY = {
|
export const SERVICES_KEY = {
|
||||||
CLUBS: "clubs",
|
CLUBS: "clubs",
|
||||||
PROFILE:"profile",
|
PROFILE: "profile",
|
||||||
EQUIPMENT: "equipment",
|
EQUIPMENT: "equipment",
|
||||||
AMICALE_WEBSITE: "amicale_website",
|
AMICALE_WEBSITE: "amicale_website",
|
||||||
VOTE: "vote",
|
VOTE: "vote",
|
||||||
|
|
@ -40,15 +49,46 @@ export const SERVICES_KEY = {
|
||||||
EMAIL: "email",
|
EMAIL: "email",
|
||||||
ENT: "ent",
|
ENT: "ent",
|
||||||
INSA_ACCOUNT: "insa_account",
|
INSA_ACCOUNT: "insa_account",
|
||||||
|
WASHERS: "washers",
|
||||||
|
DRYERS: "dryers",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const SERVICES_CATEGORIES_KEY = {
|
||||||
|
AMICALE: "amicale",
|
||||||
|
STUDENTS: "students",
|
||||||
|
INSA: "insa",
|
||||||
|
SPECIAL: "special",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type ServiceItem = {
|
||||||
|
key: string,
|
||||||
|
title: string,
|
||||||
|
subtitle: string,
|
||||||
|
image: string,
|
||||||
|
onPress: () => void,
|
||||||
|
badgeFunction?: (dashboard: fullDashboard) => number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ServiceCategory = {
|
||||||
|
key: string,
|
||||||
|
title: string,
|
||||||
|
subtitle: string,
|
||||||
|
image: string | number,
|
||||||
|
content: Array<ServiceItem>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default class ServicesManager {
|
export default class ServicesManager {
|
||||||
|
|
||||||
navigation: StackNavigationProp;
|
navigation: StackNavigationProp;
|
||||||
|
|
||||||
amicaleDataset: cardList;
|
amicaleDataset: Array<ServiceItem>;
|
||||||
studentsDataset: cardList;
|
studentsDataset: Array<ServiceItem>;
|
||||||
insaDataset: cardList;
|
insaDataset: Array<ServiceItem>;
|
||||||
|
specialDataset: Array<ServiceItem>;
|
||||||
|
|
||||||
|
categoriesDataset: Array<ServiceCategory>;
|
||||||
|
|
||||||
constructor(nav: StackNavigationProp) {
|
constructor(nav: StackNavigationProp) {
|
||||||
this.navigation = nav;
|
this.navigation = nav;
|
||||||
|
|
@ -79,7 +119,10 @@ export default class ServicesManager {
|
||||||
title: i18n.t('screens.websites.amicale'),
|
title: i18n.t('screens.websites.amicale'),
|
||||||
subtitle: i18n.t('screens.services.descriptions.amicaleWebsite'),
|
subtitle: i18n.t('screens.services.descriptions.amicaleWebsite'),
|
||||||
image: AMICALE_IMAGE,
|
image: AMICALE_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.AMICALE, title: i18n.t('screens.websites.amicale')}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.AMICALE,
|
||||||
|
title: i18n.t('screens.websites.amicale')
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.VOTE,
|
key: SERVICES_KEY.VOTE,
|
||||||
|
|
@ -96,6 +139,7 @@ export default class ServicesManager {
|
||||||
subtitle: i18n.t('screens.services.descriptions.proximo'),
|
subtitle: i18n.t('screens.services.descriptions.proximo'),
|
||||||
image: PROXIMO_IMAGE,
|
image: PROXIMO_IMAGE,
|
||||||
onPress: () => nav.navigate("proximo"),
|
onPress: () => nav.navigate("proximo"),
|
||||||
|
badgeFunction: (dashboard: fullDashboard) => dashboard.proximo_articles
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.WIKETUD,
|
key: SERVICES_KEY.WIKETUD,
|
||||||
|
|
@ -109,14 +153,21 @@ export default class ServicesManager {
|
||||||
title: "Élus Étudiants",
|
title: "Élus Étudiants",
|
||||||
subtitle: i18n.t('screens.services.descriptions.elusEtudiants'),
|
subtitle: i18n.t('screens.services.descriptions.elusEtudiants'),
|
||||||
image: EE_IMAGE,
|
image: EE_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.WIKETUD, title: "Wiketud"}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.ELUS_ETUDIANTS,
|
||||||
|
title: "Élus Étudiants"
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.TUTOR_INSA,
|
key: SERVICES_KEY.TUTOR_INSA,
|
||||||
title: "Tutor'INSA",
|
title: "Tutor'INSA",
|
||||||
subtitle: i18n.t('screens.services.descriptions.tutorInsa'),
|
subtitle: i18n.t('screens.services.descriptions.tutorInsa'),
|
||||||
image: TUTORINSA_IMAGE,
|
image: TUTORINSA_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.TUTOR_INSA, title: "Tutor'INSA"})
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.TUTOR_INSA,
|
||||||
|
title: "Tutor'INSA"
|
||||||
|
}),
|
||||||
|
badgeFunction: (dashboard: fullDashboard) => dashboard.available_tutorials
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
this.insaDataset = [
|
this.insaDataset = [
|
||||||
|
|
@ -126,41 +177,105 @@ export default class ServicesManager {
|
||||||
subtitle: i18n.t('screens.services.descriptions.self'),
|
subtitle: i18n.t('screens.services.descriptions.self'),
|
||||||
image: RU_IMAGE,
|
image: RU_IMAGE,
|
||||||
onPress: () => nav.navigate("self-menu"),
|
onPress: () => nav.navigate("self-menu"),
|
||||||
|
badgeFunction: (dashboard: fullDashboard) => dashboard.today_menu.length
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.AVAILABLE_ROOMS,
|
key: SERVICES_KEY.AVAILABLE_ROOMS,
|
||||||
title: i18n.t('screens.websites.rooms'),
|
title: i18n.t('screens.websites.rooms'),
|
||||||
subtitle: i18n.t('screens.services.descriptions.availableRooms'),
|
subtitle: i18n.t('screens.services.descriptions.availableRooms'),
|
||||||
image: ROOM_IMAGE,
|
image: ROOM_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.AVAILABLE_ROOMS, title: i18n.t('screens.websites.rooms')}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.AVAILABLE_ROOMS,
|
||||||
|
title: i18n.t('screens.websites.rooms')
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.BIB,
|
key: SERVICES_KEY.BIB,
|
||||||
title: i18n.t('screens.websites.bib'),
|
title: i18n.t('screens.websites.bib'),
|
||||||
subtitle: i18n.t('screens.services.descriptions.bib'),
|
subtitle: i18n.t('screens.services.descriptions.bib'),
|
||||||
image: BIB_IMAGE,
|
image: BIB_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.BIB, title: i18n.t('screens.websites.bib')}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.BIB,
|
||||||
|
title: i18n.t('screens.websites.bib')
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.EMAIL,
|
key: SERVICES_KEY.EMAIL,
|
||||||
title: i18n.t('screens.websites.mails'),
|
title: i18n.t('screens.websites.mails'),
|
||||||
subtitle: i18n.t('screens.services.descriptions.mails'),
|
subtitle: i18n.t('screens.services.descriptions.mails'),
|
||||||
image: EMAIL_IMAGE,
|
image: EMAIL_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.BLUEMIND, title: i18n.t('screens.websites.mails')}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.BLUEMIND,
|
||||||
|
title: i18n.t('screens.websites.mails')
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.ENT,
|
key: SERVICES_KEY.ENT,
|
||||||
title: i18n.t('screens.websites.ent'),
|
title: i18n.t('screens.websites.ent'),
|
||||||
subtitle: i18n.t('screens.services.descriptions.ent'),
|
subtitle: i18n.t('screens.services.descriptions.ent'),
|
||||||
image: ENT_IMAGE,
|
image: ENT_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.ENT, title: i18n.t('screens.websites.ent')}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.ENT,
|
||||||
|
title: i18n.t('screens.websites.ent')
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: SERVICES_KEY.INSA_ACCOUNT,
|
key: SERVICES_KEY.INSA_ACCOUNT,
|
||||||
title: i18n.t('screens.insaAccount.title'),
|
title: i18n.t('screens.insaAccount.title'),
|
||||||
subtitle: i18n.t('screens.services.descriptions.insaAccount'),
|
subtitle: i18n.t('screens.services.descriptions.insaAccount'),
|
||||||
image: ACCOUNT_IMAGE,
|
image: ACCOUNT_IMAGE,
|
||||||
onPress: () => nav.navigate("website", {host: AvailableWebsites.websites.INSA_ACCOUNT, title: i18n.t('screens.insaAccount.title')}),
|
onPress: () => nav.navigate("website", {
|
||||||
|
host: AvailableWebsites.websites.INSA_ACCOUNT,
|
||||||
|
title: i18n.t('screens.insaAccount.title')
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.specialDataset = [
|
||||||
|
{
|
||||||
|
key: SERVICES_KEY.WASHERS,
|
||||||
|
title: i18n.t('screens.proxiwash.washers'),
|
||||||
|
subtitle: i18n.t('screens.services.descriptions.washers'),
|
||||||
|
image: WASHER_IMAGE,
|
||||||
|
onPress: () => nav.navigate("proxiwash"),
|
||||||
|
badgeFunction: (dashboard: fullDashboard) => dashboard.available_washers
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: SERVICES_KEY.DRYERS,
|
||||||
|
title: i18n.t('screens.proxiwash.dryers'),
|
||||||
|
subtitle: i18n.t('screens.services.descriptions.washers'),
|
||||||
|
image: DRYER_IMAGE,
|
||||||
|
onPress: () => nav.navigate("proxiwash"),
|
||||||
|
badgeFunction: (dashboard: fullDashboard) => dashboard.available_dryers
|
||||||
|
}
|
||||||
|
];
|
||||||
|
this.categoriesDataset = [
|
||||||
|
{
|
||||||
|
key: SERVICES_CATEGORIES_KEY.AMICALE,
|
||||||
|
title: i18n.t("screens.services.categories.amicale"),
|
||||||
|
subtitle: i18n.t("screens.services.more"),
|
||||||
|
image: AMICALE_LOGO,
|
||||||
|
content: this.amicaleDataset
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: SERVICES_CATEGORIES_KEY.STUDENTS,
|
||||||
|
title: i18n.t("screens.services.categories.students"),
|
||||||
|
subtitle: i18n.t("screens.services.more"),
|
||||||
|
image: 'account-group',
|
||||||
|
content: this.studentsDataset
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: SERVICES_CATEGORIES_KEY.INSA,
|
||||||
|
title: i18n.t("screens.services.categories.insa"),
|
||||||
|
subtitle: i18n.t("screens.services.more"),
|
||||||
|
image: 'school',
|
||||||
|
content: this.insaDataset
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: SERVICES_CATEGORIES_KEY.SPECIAL,
|
||||||
|
title: i18n.t("screens.services.categories.special"),
|
||||||
|
subtitle: i18n.t("screens.services.categories.special"),
|
||||||
|
image: 'star',
|
||||||
|
content: this.specialDataset
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +300,7 @@ export default class ServicesManager {
|
||||||
* @param sourceList The item list to use as source
|
* @param sourceList The item list to use as source
|
||||||
* @returns {[]}
|
* @returns {[]}
|
||||||
*/
|
*/
|
||||||
getStrippedList(idList: Array<string>, sourceList: cardList) {
|
getStrippedList(idList: Array<string>, sourceList: Array<{key: string, [key: string]: any}>) {
|
||||||
let newArray = [];
|
let newArray = [];
|
||||||
for (let i = 0; i < sourceList.length; i++) {
|
for (let i = 0; i < sourceList.length; i++) {
|
||||||
const item = sourceList[i];
|
const item = sourceList[i];
|
||||||
|
|
@ -195,35 +310,11 @@ export default class ServicesManager {
|
||||||
return newArray;
|
return newArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a services list of items with the given ids only
|
|
||||||
*
|
|
||||||
* @param idList The ids of items to find
|
|
||||||
* @returns {[]}
|
|
||||||
*/
|
|
||||||
getServicesOfId(idList: Array<string>) {
|
|
||||||
const allServices = [
|
|
||||||
...this.amicaleDataset,
|
|
||||||
...this.studentsDataset,
|
|
||||||
...this.insaDataset,
|
|
||||||
]
|
|
||||||
let servicesFound = [];
|
|
||||||
for (let i = 0; i < allServices.length; i++) {
|
|
||||||
const item = allServices[i];
|
|
||||||
if (idList.includes(item.key)) {
|
|
||||||
servicesFound.push(item);
|
|
||||||
if (servicesFound.length === idList.length)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return servicesFound;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the list of amicale's services
|
* Gets the list of amicale's services
|
||||||
*
|
*
|
||||||
* @param excludedItems Ids of items to exclude from the returned list
|
* @param excludedItems Ids of items to exclude from the returned list
|
||||||
* @returns {cardList|*[]}
|
* @returns {Array<ServiceItem>}
|
||||||
*/
|
*/
|
||||||
getAmicaleServices(excludedItems?: Array<string>) {
|
getAmicaleServices(excludedItems?: Array<string>) {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null)
|
||||||
|
|
@ -236,7 +327,7 @@ export default class ServicesManager {
|
||||||
* Gets the list of students' services
|
* Gets the list of students' services
|
||||||
*
|
*
|
||||||
* @param excludedItems Ids of items to exclude from the returned list
|
* @param excludedItems Ids of items to exclude from the returned list
|
||||||
* @returns {cardList|*[]}
|
* @returns {Array<ServiceItem>}
|
||||||
*/
|
*/
|
||||||
getStudentServices(excludedItems?: Array<string>) {
|
getStudentServices(excludedItems?: Array<string>) {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null)
|
||||||
|
|
@ -249,7 +340,7 @@ export default class ServicesManager {
|
||||||
* Gets the list of INSA's services
|
* Gets the list of INSA's services
|
||||||
*
|
*
|
||||||
* @param excludedItems Ids of items to exclude from the returned list
|
* @param excludedItems Ids of items to exclude from the returned list
|
||||||
* @returns {cardList|*[]}
|
* @returns {Array<ServiceItem>}
|
||||||
*/
|
*/
|
||||||
getINSAServices(excludedItems?: Array<string>) {
|
getINSAServices(excludedItems?: Array<string>) {
|
||||||
if (excludedItems != null)
|
if (excludedItems != null)
|
||||||
|
|
@ -258,4 +349,30 @@ export default class ServicesManager {
|
||||||
return this.insaDataset;
|
return this.insaDataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of special services
|
||||||
|
*
|
||||||
|
* @param excludedItems Ids of items to exclude from the returned list
|
||||||
|
* @returns {Array<ServiceItem>}
|
||||||
|
*/
|
||||||
|
getSpecialServices(excludedItems?: Array<string>) {
|
||||||
|
if (excludedItems != null)
|
||||||
|
return this.getStrippedList(excludedItems, this.specialDataset)
|
||||||
|
else
|
||||||
|
return this.specialDataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all services sorted by category
|
||||||
|
*
|
||||||
|
* @param excludedItems Ids of categories to exclude from the returned list
|
||||||
|
* @returns {Array<ServiceCategory>}
|
||||||
|
*/
|
||||||
|
getCategories(excludedItems?: Array<string>) {
|
||||||
|
if (excludedItems != null)
|
||||||
|
return this.getStrippedList(excludedItems, this.categoriesDataset)
|
||||||
|
else
|
||||||
|
return this.categoriesDataset;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import SettingsScreen from '../screens/Other/SettingsScreen';
|
import SettingsScreen from '../screens/Other/Settings/SettingsScreen';
|
||||||
import AboutScreen from '../screens/About/AboutScreen';
|
import AboutScreen from '../screens/About/AboutScreen';
|
||||||
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
|
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
|
||||||
import DebugScreen from '../screens/About/DebugScreen';
|
import DebugScreen from '../screens/About/DebugScreen';
|
||||||
|
|
@ -26,6 +26,7 @@ import WebsiteScreen from "../screens/Services/WebsiteScreen";
|
||||||
import EquipmentScreen from "../screens/Amicale/Equipment/EquipmentListScreen";
|
import EquipmentScreen from "../screens/Amicale/Equipment/EquipmentListScreen";
|
||||||
import EquipmentLendScreen from "../screens/Amicale/Equipment/EquipmentRentScreen";
|
import EquipmentLendScreen from "../screens/Amicale/Equipment/EquipmentRentScreen";
|
||||||
import EquipmentConfirmScreen from "../screens/Amicale/Equipment/EquipmentConfirmScreen";
|
import EquipmentConfirmScreen from "../screens/Amicale/Equipment/EquipmentConfirmScreen";
|
||||||
|
import DashboardEditScreen from "../screens/Other/Settings/DashboardEditScreen";
|
||||||
|
|
||||||
const modalTransition = Platform.OS === 'ios' ? TransitionPresets.ModalPresentationIOS : TransitionPresets.ModalSlideFromBottomIOS;
|
const modalTransition = Platform.OS === 'ios' ? TransitionPresets.ModalPresentationIOS : TransitionPresets.ModalSlideFromBottomIOS;
|
||||||
|
|
||||||
|
|
@ -62,6 +63,13 @@ function MainStackComponent(props: { createTabNavigator: () => React.Node }) {
|
||||||
title: i18n.t('screens.settings.title'),
|
title: i18n.t('screens.settings.title'),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<MainStack.Screen
|
||||||
|
name="dashboard-edit"
|
||||||
|
component={DashboardEditScreen}
|
||||||
|
options={{
|
||||||
|
title: i18n.t('screens.settings.dashboardEdit.title'),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<MainStack.Screen
|
<MainStack.Screen
|
||||||
name="about"
|
name="about"
|
||||||
component={AboutScreen}
|
component={AboutScreen}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ import {View} from "react-native-animatable";
|
||||||
import ConnectionManager from "../../managers/ConnectionManager";
|
import ConnectionManager from "../../managers/ConnectionManager";
|
||||||
import LogoutDialog from "../../components/Amicale/LogoutDialog";
|
import LogoutDialog from "../../components/Amicale/LogoutDialog";
|
||||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
||||||
import AvailableWebsites from "../../constants/AvailableWebsites";
|
|
||||||
import {MASCOT_STYLE} from "../../components/Mascot/Mascot";
|
import {MASCOT_STYLE} from "../../components/Mascot/Mascot";
|
||||||
import MascotPopup from "../../components/Mascot/MascotPopup";
|
import MascotPopup from "../../components/Mascot/MascotPopup";
|
||||||
|
import DashboardManager from "../../managers/DashboardManager";
|
||||||
// import DATA from "../dashboard_data.json";
|
// import DATA from "../dashboard_data.json";
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ export type feedItem = {
|
||||||
id: string,
|
id: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
type fullDashboard = {
|
export type fullDashboard = {
|
||||||
today_menu: Array<{ [key: string]: any }>,
|
today_menu: Array<{ [key: string]: any }>,
|
||||||
proximo_articles: number,
|
proximo_articles: number,
|
||||||
available_dryers: number,
|
available_dryers: number,
|
||||||
|
|
@ -66,15 +66,6 @@ type dashboardItem = {
|
||||||
content: Array<{ [key: string]: any }>
|
content: Array<{ [key: string]: any }>
|
||||||
};
|
};
|
||||||
|
|
||||||
type dashboardSmallItem = {
|
|
||||||
id: string,
|
|
||||||
data: number,
|
|
||||||
icon: string,
|
|
||||||
color: string,
|
|
||||||
onPress: () => void,
|
|
||||||
isAvailable: boolean
|
|
||||||
};
|
|
||||||
|
|
||||||
export type event = {
|
export type event = {
|
||||||
id: number,
|
id: number,
|
||||||
title: string,
|
title: string,
|
||||||
|
|
@ -113,11 +104,16 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
fabRef: { current: null | AnimatedFAB };
|
fabRef: { current: null | AnimatedFAB };
|
||||||
currentNewFeed: Array<feedItem>;
|
currentNewFeed: Array<feedItem>;
|
||||||
|
currentDashboard: fullDashboard | null;
|
||||||
|
|
||||||
|
dashboardManager: DashboardManager;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.fabRef = React.createRef();
|
this.fabRef = React.createRef();
|
||||||
|
this.dashboardManager = new DashboardManager(this.props.navigation);
|
||||||
this.currentNewFeed = [];
|
this.currentNewFeed = [];
|
||||||
|
this.currentDashboard = null;
|
||||||
this.isLoggedIn = ConnectionManager.getInstance().isLoggedIn();
|
this.isLoggedIn = ConnectionManager.getInstance().isLoggedIn();
|
||||||
this.props.navigation.setOptions({
|
this.props.navigation.setOptions({
|
||||||
headerRight: this.getHeaderButton,
|
headerRight: this.getHeaderButton,
|
||||||
|
|
@ -207,22 +203,6 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
hideDisconnectDialog = () => this.setState({dialogVisible: false});
|
hideDisconnectDialog = () => this.setState({dialogVisible: false});
|
||||||
|
|
||||||
onProxiwashClick = () => {
|
|
||||||
this.props.navigation.navigate("proxiwash");
|
|
||||||
};
|
|
||||||
|
|
||||||
onProximoClick = () => {
|
|
||||||
this.props.navigation.navigate("proximo");
|
|
||||||
};
|
|
||||||
|
|
||||||
onTutorInsaClick = () => {
|
|
||||||
this.props.navigation.navigate("website", {host: AvailableWebsites.websites.TUTOR_INSA, title: "Tutor'INSA"});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMenuClick = () => {
|
|
||||||
this.props.navigation.navigate('self-menu');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the dataset to be used in the FlatList
|
* Creates the dataset to be used in the FlatList
|
||||||
*
|
*
|
||||||
|
|
@ -232,9 +212,11 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
createDataset = (fetchedData: rawDashboard) => {
|
createDataset = (fetchedData: rawDashboard) => {
|
||||||
// fetchedData = DATA;
|
// fetchedData = DATA;
|
||||||
let dashboardData;
|
let dashboardData;
|
||||||
if (fetchedData.news_feed != null) {
|
if (fetchedData.news_feed != null)
|
||||||
this.currentNewFeed = fetchedData.news_feed.data;
|
this.currentNewFeed = fetchedData.news_feed.data;
|
||||||
}
|
if (fetchedData.dashboard != null)
|
||||||
|
this.currentDashboard = fetchedData.dashboard;
|
||||||
|
|
||||||
if (fetchedData.dashboard != null)
|
if (fetchedData.dashboard != null)
|
||||||
dashboardData = this.generateDashboardDataset(fetchedData.dashboard);
|
dashboardData = this.generateDashboardDataset(fetchedData.dashboard);
|
||||||
else
|
else
|
||||||
|
|
@ -264,48 +246,7 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
{id: 'actions', content: []},
|
{id: 'actions', content: []},
|
||||||
{
|
{
|
||||||
id: 'top',
|
id: 'top',
|
||||||
content: [
|
content: this.dashboardManager.getCurrentDashboard(),
|
||||||
{
|
|
||||||
id: 'washers',
|
|
||||||
data: dashboardData == null ? 0 : dashboardData.available_washers,
|
|
||||||
icon: 'washing-machine',
|
|
||||||
color: this.props.theme.colors.proxiwashColor,
|
|
||||||
onPress: this.onProxiwashClick,
|
|
||||||
isAvailable: dashboardData == null ? false : dashboardData.available_washers > 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'dryers',
|
|
||||||
data: dashboardData == null ? 0 : dashboardData.available_dryers,
|
|
||||||
icon: 'tumble-dryer',
|
|
||||||
color: this.props.theme.colors.proxiwashColor,
|
|
||||||
onPress: this.onProxiwashClick,
|
|
||||||
isAvailable: dashboardData == null ? false : dashboardData.available_dryers > 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'available_tutorials',
|
|
||||||
data: dashboardData == null ? 0 : dashboardData.available_tutorials,
|
|
||||||
icon: 'school',
|
|
||||||
color: this.props.theme.colors.tutorinsaColor,
|
|
||||||
onPress: this.onTutorInsaClick,
|
|
||||||
isAvailable: dashboardData == null ? false : dashboardData.available_tutorials > 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'proximo_articles',
|
|
||||||
data: dashboardData == null ? 0 : dashboardData.proximo_articles,
|
|
||||||
icon: 'shopping',
|
|
||||||
color: this.props.theme.colors.proximoColor,
|
|
||||||
onPress: this.onProximoClick,
|
|
||||||
isAvailable: dashboardData == null ? false : dashboardData.proximo_articles > 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'today_menu',
|
|
||||||
data: dashboardData == null ? [] : dashboardData.today_menu,
|
|
||||||
icon: 'silverware-fork-knife',
|
|
||||||
color: this.props.theme.colors.menuColor,
|
|
||||||
onPress: this.onMenuClick,
|
|
||||||
isAvailable: dashboardData == null ? false : dashboardData.today_menu.length > 0
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'event',
|
id: 'event',
|
||||||
|
|
@ -491,14 +432,14 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
* @param item
|
* @param item
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
dashboardRowRenderItem = ({item}: { item: dashboardSmallItem }) => {
|
dashboardRowRenderItem = ({item}: { item: DashboardItem }) => {
|
||||||
return (
|
return (
|
||||||
<SquareDashboardItem
|
<SquareDashboardItem
|
||||||
color={item.color}
|
image={item.image}
|
||||||
icon={item.icon}
|
onPress={item.onPress}
|
||||||
clickAction={item.onPress}
|
badgeCount={this.currentDashboard != null && item.badgeFunction != null
|
||||||
isAvailable={item.isAvailable}
|
? item.badgeFunction(this.currentDashboard)
|
||||||
badgeNumber={item.data}
|
: null}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -509,7 +450,7 @@ class HomeScreen extends React.Component<Props, State> {
|
||||||
* @param content
|
* @param content
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
getDashboardRow(content: Array<dashboardSmallItem>) {
|
getDashboardRow(content: Array<DashboardItem>) {
|
||||||
return (
|
return (
|
||||||
//$FlowFixMe
|
//$FlowFixMe
|
||||||
<FlatList
|
<FlatList
|
||||||
|
|
|
||||||
148
src/screens/Other/Settings/DashboardEditScreen.js
Normal file
148
src/screens/Other/Settings/DashboardEditScreen.js
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import {StackNavigationProp} from "@react-navigation/stack";
|
||||||
|
import type {CustomTheme} from "../../../managers/ThemeManager";
|
||||||
|
import {Button, Paragraph, withTheme} from "react-native-paper";
|
||||||
|
import type {ServiceCategory, ServiceItem} from "../../../managers/ServicesManager";
|
||||||
|
import DashboardManager from "../../../managers/DashboardManager";
|
||||||
|
import DashboardItem from "../../../components/Home/EventDashboardItem";
|
||||||
|
import {FlatList} from "react-native";
|
||||||
|
import {View} from "react-native-animatable";
|
||||||
|
import DashboardEditAccordion from "../../../components/Lists/DashboardEdit/DashboardEditAccordion";
|
||||||
|
import DashboardEditPreviewItem from "../../../components/Lists/DashboardEdit/DashboardEditPreviewItem";
|
||||||
|
import AsyncStorageManager from "../../../managers/AsyncStorageManager";
|
||||||
|
import i18n from "i18n-js";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
navigation: StackNavigationProp,
|
||||||
|
theme: CustomTheme,
|
||||||
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
currentDashboard: Array<ServiceItem>,
|
||||||
|
currentDashboardIdList: Array<string>,
|
||||||
|
activeItem: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class defining the Settings screen. This screen shows controls to modify app preferences.
|
||||||
|
*/
|
||||||
|
class DashboardEditScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
|
content: Array<ServiceCategory>;
|
||||||
|
initialDashboard: Array<ServiceItem>;
|
||||||
|
initialDashboardIdList: Array<string>;
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
let dashboardManager = new DashboardManager(this.props.navigation);
|
||||||
|
this.initialDashboardIdList = JSON.parse(AsyncStorageManager.getInstance().preferences.dashboardItems.current);
|
||||||
|
this.initialDashboard = dashboardManager.getCurrentDashboard();
|
||||||
|
this.state = {
|
||||||
|
currentDashboard: [...this.initialDashboard],
|
||||||
|
currentDashboardIdList: [...this.initialDashboardIdList],
|
||||||
|
activeItem: 0,
|
||||||
|
}
|
||||||
|
this.content = dashboardManager.getCategories();
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardRowRenderItem = ({item, index}: { item: DashboardItem, index: number }) => {
|
||||||
|
return (
|
||||||
|
<DashboardEditPreviewItem
|
||||||
|
image={item.image}
|
||||||
|
onPress={() => this.setState({activeItem: index})}
|
||||||
|
isActive={this.state.activeItem === index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
getDashboard(content: Array<DashboardItem>) {
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
data={content}
|
||||||
|
extraData={this.state}
|
||||||
|
renderItem={this.dashboardRowRenderItem}
|
||||||
|
horizontal={true}
|
||||||
|
contentContainerStyle={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
/>);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderItem = ({item}: { item: ServiceCategory }) => {
|
||||||
|
return (
|
||||||
|
<DashboardEditAccordion
|
||||||
|
item={item}
|
||||||
|
onPress={this.updateDashboard}
|
||||||
|
activeDashboard={this.state.currentDashboardIdList}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
updateDashboard = (service: ServiceItem) => {
|
||||||
|
let currentDashboard = this.state.currentDashboard;
|
||||||
|
let currentDashboardIdList = this.state.currentDashboardIdList;
|
||||||
|
currentDashboard[this.state.activeItem] = service;
|
||||||
|
currentDashboardIdList[this.state.activeItem] = service.key;
|
||||||
|
this.setState({
|
||||||
|
currentDashboard: currentDashboard,
|
||||||
|
currentDashboardIdList: currentDashboardIdList,
|
||||||
|
});
|
||||||
|
AsyncStorageManager.getInstance().savePref(
|
||||||
|
AsyncStorageManager.getInstance().preferences.dashboardItems.key,
|
||||||
|
JSON.stringify(currentDashboardIdList)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
undoDashboard= () => {
|
||||||
|
this.setState({
|
||||||
|
currentDashboard: [...this.initialDashboard],
|
||||||
|
currentDashboardIdList: [...this.initialDashboardIdList]
|
||||||
|
});
|
||||||
|
AsyncStorageManager.getInstance().savePref(
|
||||||
|
AsyncStorageManager.getInstance().preferences.dashboardItems.key,
|
||||||
|
JSON.stringify(this.initialDashboardIdList)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<View style={{
|
||||||
|
padding: 5
|
||||||
|
}}>
|
||||||
|
<Button
|
||||||
|
mode={"contained"}
|
||||||
|
onPress={this.undoDashboard}
|
||||||
|
style={{
|
||||||
|
marginLeft: "auto",
|
||||||
|
marginRight: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n.t("screens.settings.dashboardEdit.undo")}
|
||||||
|
</Button>
|
||||||
|
<View style={{
|
||||||
|
height: 50
|
||||||
|
}}>
|
||||||
|
{this.getDashboard(this.state.currentDashboard)}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<FlatList
|
||||||
|
data={this.content}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
ListHeaderComponent={<Paragraph>{i18n.t("screens.settings.dashboardEdit.message")}</Paragraph>}
|
||||||
|
style={{
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme(DashboardEditScreen);
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {ScrollView, View} from "react-native";
|
import {ScrollView, View} from "react-native";
|
||||||
import type {CustomTheme} from "../../managers/ThemeManager";
|
import type {CustomTheme} from "../../../managers/ThemeManager";
|
||||||
import ThemeManager from '../../managers/ThemeManager';
|
import ThemeManager from '../../../managers/ThemeManager';
|
||||||
import i18n from "i18n-js";
|
import i18n from "i18n-js";
|
||||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
import AsyncStorageManager from "../../../managers/AsyncStorageManager";
|
||||||
import {Card, List, Switch, ToggleButton, withTheme} from 'react-native-paper';
|
import {Card, List, Switch, ToggleButton, withTheme} from 'react-native-paper';
|
||||||
import {Appearance} from "react-native-appearance";
|
import {Appearance} from "react-native-appearance";
|
||||||
import CustomSlider from "../../components/Overrides/CustomSlider";
|
import CustomSlider from "../../../components/Overrides/CustomSlider";
|
||||||
import {StackNavigationProp} from "@react-navigation/stack";
|
import {StackNavigationProp} from "@react-navigation/stack";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -203,6 +203,12 @@ class SettingsScreen extends React.Component<Props, State> {
|
||||||
left={props => <List.Icon {...props} icon="power"/>}
|
left={props => <List.Icon {...props} icon="power"/>}
|
||||||
/>
|
/>
|
||||||
{this.getStartScreenPicker()}
|
{this.getStartScreenPicker()}
|
||||||
|
<List.Item
|
||||||
|
title={i18n.t('screens.settings.dashboard')}
|
||||||
|
description={i18n.t('screens.settings.dashboardSub')}
|
||||||
|
onPress={() => this.props.navigation.navigate("dashboard-edit")}
|
||||||
|
left={props => <List.Icon {...props} icon="view-dashboard"/>}
|
||||||
|
/>
|
||||||
</List.Section>
|
</List.Section>
|
||||||
</Card>
|
</Card>
|
||||||
<Card style={{margin: 5}}>
|
<Card style={{margin: 5}}>
|
||||||
|
|
@ -16,7 +16,7 @@ import {StackNavigationProp} from "@react-navigation/stack";
|
||||||
import {MASCOT_STYLE} from "../../components/Mascot/Mascot";
|
import {MASCOT_STYLE} from "../../components/Mascot/Mascot";
|
||||||
import MascotPopup from "../../components/Mascot/MascotPopup";
|
import MascotPopup from "../../components/Mascot/MascotPopup";
|
||||||
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
import AsyncStorageManager from "../../managers/AsyncStorageManager";
|
||||||
import ServicesManager from "../../managers/ServicesManager";
|
import ServicesManager, {SERVICES_CATEGORIES_KEY} from "../../managers/ServicesManager";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
navigation: StackNavigationProp,
|
navigation: StackNavigationProp,
|
||||||
|
|
@ -36,14 +36,9 @@ export type listItem = {
|
||||||
content: cardList,
|
content: cardList,
|
||||||
}
|
}
|
||||||
|
|
||||||
const AMICALE_LOGO = require("../../../assets/amicale.png");
|
|
||||||
|
|
||||||
class ServicesScreen extends React.Component<Props, State> {
|
class ServicesScreen extends React.Component<Props, State> {
|
||||||
|
|
||||||
amicaleDataset: cardList;
|
|
||||||
studentsDataset: cardList;
|
|
||||||
insaDataset: cardList;
|
|
||||||
|
|
||||||
finalDataset: Array<listItem>
|
finalDataset: Array<listItem>
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
|
@ -53,29 +48,7 @@ class ServicesScreen extends React.Component<Props, State> {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
const services = new ServicesManager(props.navigation);
|
const services = new ServicesManager(props.navigation);
|
||||||
this.amicaleDataset = services.getAmicaleServices();
|
this.finalDataset = services.getCategories([SERVICES_CATEGORIES_KEY.SPECIAL])
|
||||||
this.studentsDataset = services.getStudentServices();
|
|
||||||
this.insaDataset = services.getINSAServices();
|
|
||||||
this.finalDataset = [
|
|
||||||
{
|
|
||||||
title: i18n.t("screens.services.categories.amicale"),
|
|
||||||
description: i18n.t("screens.services.more"),
|
|
||||||
image: AMICALE_LOGO,
|
|
||||||
content: this.amicaleDataset
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: i18n.t("screens.services.categories.students"),
|
|
||||||
description: i18n.t("screens.services.more"),
|
|
||||||
image: 'account-group',
|
|
||||||
content: this.studentsDataset
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: i18n.t("screens.services.categories.insa"),
|
|
||||||
description: i18n.t("screens.services.more"),
|
|
||||||
image: 'school',
|
|
||||||
content: this.insaDataset
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
|
||||||
37
src/utils/Utils.js
Normal file
37
src/utils/Utils.js
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a sublist of the given list with items of the given ids only
|
||||||
|
*
|
||||||
|
* The given list must have a field id or key
|
||||||
|
*
|
||||||
|
* @param idList The ids of items to find
|
||||||
|
* @param originalList The original list
|
||||||
|
* @returns {[]}
|
||||||
|
*/
|
||||||
|
export function getSublistWithIds(
|
||||||
|
idList: Array<string>,
|
||||||
|
originalList: Array<{ key: string, [key: string]: any }>
|
||||||
|
): Array<{ key: string, [key: string]: any }> {
|
||||||
|
let subList = [];
|
||||||
|
for (let i = 0; i < subList.length; i++) {
|
||||||
|
subList.push(null);
|
||||||
|
}
|
||||||
|
let itemsAdded = 0;
|
||||||
|
for (let i = 0; i < originalList.length; i++) {
|
||||||
|
const item = originalList[i];
|
||||||
|
if (idList.includes(item.key)) {
|
||||||
|
subList[idList.indexOf(item.key)] = item;
|
||||||
|
itemsAdded++;
|
||||||
|
if (itemsAdded === idList.length)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < subList.length; i++) {
|
||||||
|
if (subList[i] == null)
|
||||||
|
subList.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subList;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue