Compare commits
6 commits
133df5bdb7
...
3d482753ed
Author | SHA1 | Date | |
---|---|---|---|
|
3d482753ed | ||
|
195cc68389 | ||
|
e2ad2476b6 | ||
|
a4c602c098 | ||
|
19290a96b1 | ||
|
f16f121dc4 |
|
@ -148,7 +148,7 @@ android {
|
||||||
applicationId 'fr.amicaleinsat.application'
|
applicationId 'fr.amicaleinsat.application'
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 42
|
versionCode 41
|
||||||
versionName "4.0.1"
|
versionName "4.0.1"
|
||||||
missingDimensionStrategy 'react-native-camera', 'general'
|
missingDimensionStrategy 'react-native-camera', 'general'
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 28 KiB |
|
@ -1,35 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108"
|
|
||||||
android:autoMirrored="true"
|
|
||||||
tools:ignore="VectorRaster">
|
|
||||||
<group android:scaleX="0.9327526"
|
|
||||||
android:scaleY="0.9327526"
|
|
||||||
android:translateX="-9.18"
|
|
||||||
android:translateY="-9.18">
|
|
||||||
<path
|
|
||||||
android:pathData="m66.726,45.46 l20.999,26.022 0.539,-27.06 84.903,83.371 -42.449,44.716 -83.531,-81.39z" android:strokeAlpha="0">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:startY="60"
|
|
||||||
android:startX="60"
|
|
||||||
android:endY="100"
|
|
||||||
android:endX="100"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#22000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path android:fillColor="#fff"
|
|
||||||
android:pathData="m66.678,45.377 l19.491,45.744h-38.982zM76.093,44.347h12.186v31.47z" android:strokeAlpha="0"/>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
|
@ -1,17 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24"
|
|
||||||
android:tint="#FFFFFF">
|
|
||||||
<group android:scaleX="0.12773363"
|
|
||||||
android:scaleY="0.12773363"
|
|
||||||
android:translateX="3.3479624"
|
|
||||||
android:translateY="3.3479624">
|
|
||||||
<path
|
|
||||||
android:pathData="m64.695,3.346 l56.134,131.74h-112.27zM91.81,0.379h35.096v90.634z"
|
|
||||||
android:strokeAlpha="0"
|
|
||||||
android:strokeWidth="2.88"
|
|
||||||
android:fillColor="#fff"/>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 478 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 340 B After Width: | Height: | Size: 823 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 674 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 969 B After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">#C32733</color>
|
|
||||||
</resources>
|
|
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
|
@ -128,7 +128,7 @@
|
||||||
"noGroupSelected": "No group selected. Please select your group using the big beautiful red button bellow.",
|
"noGroupSelected": "No group selected. Please select your group using the big beautiful red button bellow.",
|
||||||
"favorites": "Favorites",
|
"favorites": "Favorites",
|
||||||
"mascotDialog": {
|
"mascotDialog": {
|
||||||
"title": "Don't skip class",
|
"title": "Skipping classes is bad",
|
||||||
"message": "Here is Planex! You can set your class and your crush's to favorites in order to find them back easily!\n\nIf you mainly use Campus for Planex, go to the settings to make the app directly start on it!",
|
"message": "Here is Planex! You can set your class and your crush's to favorites in order to find them back easily!\n\nIf you mainly use Campus for Planex, go to the settings to make the app directly start on it!",
|
||||||
"ok": "Settings",
|
"ok": "Settings",
|
||||||
"cancel": "Later"
|
"cancel": "Later"
|
||||||
|
@ -363,15 +363,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"feedback": {
|
"feedback": {
|
||||||
"title": "Contribute",
|
"title": "Feedback",
|
||||||
"feedback": "Contact the dev",
|
"bugs": "Report Bugs",
|
||||||
"feedbackSubtitle": "A student like you!",
|
"bugsSubtitle": "Did you find a bug? Let us know!",
|
||||||
"feedbackDescription": "Feedback or bugs, you are always welcome.\nChoose your preferred way from the buttons bellow.",
|
"bugsDescription": "Reporting bugs helps us make the app better. To do so, use one of the buttons below and be as precise as possible when describing your problem!",
|
||||||
"contribute": "Contribute to the project",
|
"feedbackSubtitle": "Let us know what you think!",
|
||||||
"contributeSubtitle": "With a possible \"implication citoyenne\"!",
|
"feedbackDescription": "Do you have a feature you want to be added/changed/removed, want to give your opinion on the app or simply chat with the dev? Use one of the links below!",
|
||||||
"contributeDescription": "Everyone can help: communication, design or coding! You are free to contribute as you like.\nYou can find bellow a link to Trello for project organization, and a link to the source code on GitEtud.",
|
"contactMeans": "Using Gitea is recommended, to use it simply login with your INSA account.",
|
||||||
"homeButtonTitle": "Contribute to the project",
|
"homeButtonTitle": "Feedback/Bug report",
|
||||||
"homeButtonSubtitle": "Your help is important"
|
"homeButtonSubtitle": "Contact the devs"
|
||||||
},
|
},
|
||||||
"game": {
|
"game": {
|
||||||
"title": "So Awesome Game",
|
"title": "So Awesome Game",
|
||||||
|
@ -422,16 +422,16 @@
|
||||||
"text": "You can do much more with CAMPUS, but I can't explain everything here. Explore the app to find out!"
|
"text": "You can do much more with CAMPUS, but I can't explain everything here. Explore the app to find out!"
|
||||||
},
|
},
|
||||||
"slideDone": {
|
"slideDone": {
|
||||||
"title": "Contribute to the project!",
|
"title": "Your feedback is valuable!",
|
||||||
"text": "This app is the work of one student, so your feedback and your help are welcome!\nEveryone can help: communication, design or coding!"
|
"text": "This app is the work of one student (with some help here and there), so your feedback is much appreciated!"
|
||||||
},
|
},
|
||||||
"updateSlide0": {
|
"updateSlide0": {
|
||||||
"title": "Hi you!",
|
"title": "New in this update!",
|
||||||
"text": "I'm new here and I will help you around the app. My thing is to give you lots of tips and tricks."
|
"text": "Hello you! I'm here to help you around the app."
|
||||||
},
|
},
|
||||||
"updateSlide1": {
|
"updateSlide1": {
|
||||||
"title": "Contribute to the project!",
|
"title": "Contribute!",
|
||||||
"text": "This app is the work of one student, so your feedback and your help are welcome!\nEveryone can help: communication, design or coding!"
|
"text": "Everyone is free to contribute to the project, from reporting bugs to implementing new features"
|
||||||
},
|
},
|
||||||
"aprilFoolsSlide": {
|
"aprilFoolsSlide": {
|
||||||
"title": "New in this update!",
|
"title": "New in this update!",
|
||||||
|
|
|
@ -362,15 +362,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"feedback": {
|
"feedback": {
|
||||||
"title": "Participer",
|
"title": "Feedback",
|
||||||
"feedback": "Contacte le développeur",
|
"bugs": "Rapporter des Bugs",
|
||||||
"feedbackSubtitle": "C'est un étudiant comme toi !",
|
"bugsSubtitle": "Tu as trouvé un bug ?",
|
||||||
"feedbackDescription": "Que ce soit pour donner ton avis ou rapporter des bugs, tu es le bienvenue.\nUtilise le moyen de ton choix parmi les boutons ci-dessous.",
|
"bugsDescription": "Rapporter les bugs m'aide à améliorer l'appli. Pour cela, merci d'utiliser un des boutons ci-dessous et de décrire ton problème le plus précisément possible !",
|
||||||
"contribute": "Contribue au projet",
|
"feedbackSubtitle": "Dis moi ce que tu penses !",
|
||||||
"contributeSubtitle": "Avec une possible implication citoyenne !",
|
"feedbackDescription": "Tu veux voir une fonctionnalité ajoutée/modifiée/supprimée ? Tu veux donner ton opinion sur l'appli ou simplement discuter avec le développeur (c'est moi coucou) ? Utilise un des liens ci-dessous !",
|
||||||
"contributeDescription": "Il y en a pour tous les goûts : de la com', du design ou de la technique. Tu es libre de participer comme tu veux.\nTu trouveras ci-dessous un Trello de l'organisation du projet, ainsi que le code source sur GitEtud.",
|
"contactMeans": "L'utilisation de Gitea est recommandée, pour l'utiliser, connecte toi avec tes identifiants INSA.",
|
||||||
"homeButtonTitle": "Participer au projet",
|
"homeButtonTitle": "Feedback/Bugs",
|
||||||
"homeButtonSubtitle": "Ton aide compte"
|
"homeButtonSubtitle": "Contacte le développeur de l'appli"
|
||||||
},
|
},
|
||||||
"game": {
|
"game": {
|
||||||
"title": "Jeu trop ouf",
|
"title": "Jeu trop ouf",
|
||||||
|
@ -421,16 +421,16 @@
|
||||||
"text": "Tu peux faire bien plus avec CAMPUS, mais je n'ai pas le temps de tout dire ici. Balade toi sur l'appli pour tout découvrir !"
|
"text": "Tu peux faire bien plus avec CAMPUS, mais je n'ai pas le temps de tout dire ici. Balade toi sur l'appli pour tout découvrir !"
|
||||||
},
|
},
|
||||||
"slideDone": {
|
"slideDone": {
|
||||||
"title": "Participe au projet !",
|
"title": "Ton avis compte !",
|
||||||
"text": "Cette appli à été réalisée par un seul étudiant, donc tes retours et ton aide sont les bienvenus !\nIl y en a pour tous les goûts : de la com', du design ou de la technique !"
|
"text": "Cette appli à été réalisée par un seul étudiant (avec un peu d'aide par-ci par-là), donc tes retours sont les bienvenus !"
|
||||||
},
|
},
|
||||||
"updateSlide0": {
|
"updateSlide0": {
|
||||||
"title": "Coucou toi !",
|
"title": "Nouveau dans cette mise à jour !",
|
||||||
"text": "Je suis le petit nouveau qui t'accompagnera sur l'appli. Mon dada c'est de te donner plein d'astuces et d'infos."
|
"text": "Coucou toi ! Je suis là pour t'aider trouver à utiliser l'appli."
|
||||||
},
|
},
|
||||||
"updateSlide1": {
|
"updateSlide1": {
|
||||||
"title": "Participe au projet !",
|
"title": "Participe au projet !",
|
||||||
"text": "Cette appli à été réalisée par un seul étudiant, donc tes retours et ton aide sont les bienvenus !\nIl y en a pour tous les goûts : de la com', du design ou de la technique !"
|
"text": "Tout le monde peut participer, que ce soit pour trouver des bugs ou ajouter des nouvelles fonctionnalités."
|
||||||
},
|
},
|
||||||
"aprilFoolsSlide": {
|
"aprilFoolsSlide": {
|
||||||
"title": "Nouveau dans cette mise à jour !",
|
"title": "Nouveau dans cette mise à jour !",
|
||||||
|
|
|
@ -4,12 +4,12 @@ import * as React from 'react';
|
||||||
import {StyleSheet, View} from 'react-native';
|
import {StyleSheet, View} from 'react-native';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import {Avatar, Button, Card, TouchableRipple} from 'react-native-paper';
|
import {Avatar, Button, Card, TouchableRipple} from 'react-native-paper';
|
||||||
import {getTimeOnlyString, isDescriptionEmpty} from '../../utils/Planning';
|
import {getFormattedEventTime, isDescriptionEmpty} from '../../utils/Planning';
|
||||||
import CustomHTML from '../Overrides/CustomHTML';
|
import CustomHTML from '../Overrides/CustomHTML';
|
||||||
import type {PlanningEventType} from '../../utils/Planning';
|
import type {EventType} from '../../screens/Home/HomeScreen';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
event?: PlanningEventType | null,
|
event?: EventType | null,
|
||||||
clickAction: () => void,
|
clickAction: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,13 +62,19 @@ class PreviewEventDashboardItem extends React.Component<PropsType> {
|
||||||
{hasImage ? (
|
{hasImage ? (
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={event.title}
|
title={event.title}
|
||||||
subtitle={getTimeOnlyString(event.date_begin)}
|
subtitle={getFormattedEventTime(
|
||||||
|
event.date_begin,
|
||||||
|
event.date_end,
|
||||||
|
)}
|
||||||
left={getImage}
|
left={getImage}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={event.title}
|
title={event.title}
|
||||||
subtitle={getTimeOnlyString(event.date_begin)}
|
subtitle={getFormattedEventTime(
|
||||||
|
event.date_begin,
|
||||||
|
event.date_end,
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isEmpty ? (
|
{!isEmpty ? (
|
||||||
|
|
|
@ -24,7 +24,7 @@ class MascotIntroEnd extends React.Component<null> {
|
||||||
<Mascot
|
<Mascot
|
||||||
style={{
|
style={{
|
||||||
...styles.center,
|
...styles.center,
|
||||||
width: '80%',
|
height: '80%',
|
||||||
}}
|
}}
|
||||||
emotion={MASCOT_STYLE.COOL}
|
emotion={MASCOT_STYLE.COOL}
|
||||||
animated
|
animated
|
||||||
|
|
|
@ -26,7 +26,7 @@ class MascotIntroWelcome extends React.Component<null> {
|
||||||
<Mascot
|
<Mascot
|
||||||
style={{
|
style={{
|
||||||
...styles.center,
|
...styles.center,
|
||||||
width: '80%',
|
height: '80%',
|
||||||
}}
|
}}
|
||||||
emotion={MASCOT_STYLE.NORMAL}
|
emotion={MASCOT_STYLE.NORMAL}
|
||||||
animated
|
animated
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {FlatList, Linking, Platform, Image, View} from 'react-native';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import {Avatar, Card, List, withTheme} from 'react-native-paper';
|
import {Avatar, Card, List, withTheme} from 'react-native-paper';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import {Modalize} from "react-native-modalize";
|
import {Modalize} from 'react-native-modalize';
|
||||||
import packageJson from '../../../package.json';
|
import packageJson from '../../../package.json';
|
||||||
import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
|
import CollapsibleFlatList from '../../components/Collapsible/CollapsibleFlatList';
|
||||||
import APP_LOGO from '../../../assets/android.icon.round.png';
|
import APP_LOGO from '../../../assets/android.icon.round.png';
|
||||||
|
@ -13,8 +13,7 @@ import type {
|
||||||
CardTitleIconPropsType,
|
CardTitleIconPropsType,
|
||||||
ListIconPropsType,
|
ListIconPropsType,
|
||||||
} from '../../constants/PaperStyles';
|
} from '../../constants/PaperStyles';
|
||||||
import OptionsDialog from "../../components/Dialogs/OptionsDialog";
|
import OptionsDialog from '../../components/Dialogs/OptionsDialog';
|
||||||
import type {OptionsDialogButtonType} from "../../components/Dialogs/OptionsDialog";
|
|
||||||
|
|
||||||
type ListItemType = {
|
type ListItemType = {
|
||||||
onPressCallback: () => void,
|
onPressCallback: () => void,
|
||||||
|
@ -82,9 +81,9 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
*/
|
*/
|
||||||
teamUsers = {
|
teamUsers = {
|
||||||
arnaud: {
|
arnaud: {
|
||||||
name: 'Arnaud VERGNET',
|
name: 'Arnaud Vergnrt',
|
||||||
message: 'C vrément tro 1 bg !!',
|
message: i18n.t('screens.about.user.arnaud'),
|
||||||
icon: 'account-circle',
|
icon: 'crown',
|
||||||
btnTrool: {
|
btnTrool: {
|
||||||
title: 'SWAG',
|
title: 'SWAG',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
|
@ -92,13 +91,15 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
btnLinkedin: {
|
btnLinkedin: {
|
||||||
title: 'Linkedin',
|
title: '',
|
||||||
|
icon: 'linkedin',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
openWebLink(links.arnaudMail);
|
openWebLink(links.arnaudMail);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
btnMail: {
|
btnMail: {
|
||||||
title: i18n.t('screens.about.authorMail'),
|
title: '',
|
||||||
|
icon: 'email-edit',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
openWebLink(links.arnaudLinkedin);
|
openWebLink(links.arnaudLinkedin);
|
||||||
},
|
},
|
||||||
|
@ -106,22 +107,38 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
},
|
},
|
||||||
yohan: {
|
yohan: {
|
||||||
name: 'Yohan Simard',
|
name: 'Yohan Simard',
|
||||||
message: 'Correction de quelques bugs',
|
message: i18n.t('screens.about.user.yohan'),
|
||||||
icon: 'account-circle',
|
icon: 'xml',
|
||||||
btnTrool: null,
|
btnTrool: null,
|
||||||
btnLinkedin: {
|
btnLinkedin: {
|
||||||
title: 'Linkedin',
|
title: '',
|
||||||
|
icon: 'linkedin',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
openWebLink(links.yohanLinkedin);
|
openWebLink(links.yohanLinkedin);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
btnMail: {
|
btnMail: {
|
||||||
title: i18n.t('screens.about.authorMail'),
|
title: '',
|
||||||
|
icon: 'email-edit',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
openWebLink(links.yohanMail);
|
openWebLink(links.yohanMail);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
you: {
|
||||||
|
name: i18n.t('screens.about.user.youName'),
|
||||||
|
message: i18n.t('screens.about.user.you'),
|
||||||
|
icon: 'hand-pointing-right',
|
||||||
|
btnTrool: {
|
||||||
|
title: '',
|
||||||
|
icon: 'git',
|
||||||
|
onPress: () => {
|
||||||
|
openWebLink(links.git);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
btnLinkedin: null,
|
||||||
|
btnMail: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,40 +147,40 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
thanksUsers = {
|
thanksUsers = {
|
||||||
beranger: {
|
beranger: {
|
||||||
name: 'Béranger Quintana Y Arciosana',
|
name: 'Béranger Quintana Y Arciosana',
|
||||||
message: 'Étudiant en AE (2020) et Président de l’Amicale au moment de la création et du lancement du projet. L’application, c’était son idée. Il a beaucoup aidé pour trouver des bugs, de nouvelles fonctionnalités et faire de la com.',
|
message: i18n.t('screens.about.user.beranger'),
|
||||||
icon: 'account-circle',
|
icon: 'account-heart',
|
||||||
btnTrool: null,
|
btnTrool: null,
|
||||||
btnLinkedin: null,
|
btnLinkedin: null,
|
||||||
btnMail: null,
|
btnMail: null,
|
||||||
},
|
},
|
||||||
celine: {
|
celine: {
|
||||||
name: 'Céline Tassin',
|
name: 'Céline Tassin',
|
||||||
message: 'Étudiante en GPE (2020). Sans elle, tout serait moins mignon. Elle a aidé pour écrire le texte, faire de la com, et aussi à créer la mascotte 🦊.',
|
message: i18n.t('screens.about.user.celine'),
|
||||||
icon: 'account-circle',
|
icon: 'brush',
|
||||||
btnTrool: null,
|
btnTrool: null,
|
||||||
btnLinkedin: null,
|
btnLinkedin: null,
|
||||||
btnMail: null,
|
btnMail: null,
|
||||||
},
|
},
|
||||||
damien: {
|
damien: {
|
||||||
name: 'Damien Molina',
|
name: 'Damien Molina',
|
||||||
message: 'Étudiant en IR (2020) et créateur de la dernière version du site de l’Amicale. Grâce à son aide, intégrer les services de l’Amicale à l’application a été très simple.',
|
message: i18n.t('screens.about.user.damien'),
|
||||||
icon: 'account-circle',
|
icon: 'web',
|
||||||
btnTrool: null,
|
btnTrool: null,
|
||||||
btnLinkedin: null,
|
btnLinkedin: null,
|
||||||
btnMail: null,
|
btnMail: null,
|
||||||
},
|
},
|
||||||
titouan: {
|
titouan: {
|
||||||
name: 'Titouan Labourdette',
|
name: 'Titouan Labourdette',
|
||||||
message: 'Étudiant en AE (2020) et Président de l’Amicale au moment de la création et du lancement du projet. L’application, c’était son idée. Il a beaucoup aidé pour trouver des bugs, de nouvelles fonctionnalités et faire de la com.',
|
message: i18n.t('screens.about.user.titouan'),
|
||||||
icon: 'account-circle',
|
icon: 'shield-bug',
|
||||||
btnTrool: null,
|
btnTrool: null,
|
||||||
btnLinkedin: null,
|
btnLinkedin: null,
|
||||||
btnMail: null,
|
btnMail: null,
|
||||||
},
|
},
|
||||||
theo: {
|
theo: {
|
||||||
name: 'Théo Tami',
|
name: 'Théo Tami',
|
||||||
message: 'Étudiant en IR (2020). Il a beaucoup aidé pour trouver des bugs et proposer des nouvelles fonctionnalités.',
|
message: i18n.t('screens.about.user.theo'),
|
||||||
icon: 'account-circle',
|
icon: 'food-apple',
|
||||||
btnTrool: null,
|
btnTrool: null,
|
||||||
btnLinkedin: null,
|
btnLinkedin: null,
|
||||||
btnMail: null,
|
btnMail: null,
|
||||||
|
@ -240,6 +257,14 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
text: this.teamUsers.yohan.name,
|
text: this.teamUsers.yohan.name,
|
||||||
showChevron: false,
|
showChevron: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
onPressCallback: () => {
|
||||||
|
this.onListItemPress(this.teamUsers.you);
|
||||||
|
},
|
||||||
|
icon: this.teamUsers.you.icon,
|
||||||
|
text: this.teamUsers.you.name,
|
||||||
|
showChevron: false,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -346,16 +371,16 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
* Callback used when clicking an article in the list.
|
* Callback used when clicking an article in the list.
|
||||||
* It opens the modal to show detailed information about the article
|
* It opens the modal to show detailed information about the article
|
||||||
*
|
*
|
||||||
* @param user TODO
|
* @param user A user key
|
||||||
*/
|
*/
|
||||||
onListItemPress(user: AthorsItemType) {
|
onListItemPress(user: AthorsItemType) {
|
||||||
const dialogBtn: Array<OptionsDialogButtonType> = [
|
const dialogBtn: Array<IconOptionsDialogButtonType> = [
|
||||||
{
|
{
|
||||||
title: 'OK',
|
title: 'OK',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
this.onDialogDismiss();
|
this.setState({dialogVisible: false});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
|
||||||
];
|
];
|
||||||
if (user.btnMail != null) {
|
if (user.btnMail != null) {
|
||||||
dialogBtn.push(user.btnMail);
|
dialogBtn.push(user.btnMail);
|
||||||
|
@ -430,7 +455,7 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the thanks card showing information and links about the team TODO
|
* Get the thank you card showing support information and links
|
||||||
*
|
*
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
|
@ -465,7 +490,7 @@ class AboutScreen extends React.Component<PropsType> {
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={i18n.t('screens.about.technologies')}
|
title={i18n.t('screens.about.technologies')}
|
||||||
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
||||||
<Avatar.Icon size={iconProps.size} icon="build" />
|
<Avatar.Icon size={iconProps.size} icon="wrench" />
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
|
|
|
@ -28,7 +28,6 @@ import MascotPopup from '../../components/Mascot/MascotPopup';
|
||||||
import DashboardManager from '../../managers/DashboardManager';
|
import DashboardManager from '../../managers/DashboardManager';
|
||||||
import type {ServiceItemType} from '../../managers/ServicesManager';
|
import type {ServiceItemType} from '../../managers/ServicesManager';
|
||||||
import {getDisplayEvent, getFutureEvents} from '../../utils/Home';
|
import {getDisplayEvent, getFutureEvents} from '../../utils/Home';
|
||||||
import type {PlanningEventType} from '../../utils/Planning';
|
|
||||||
// import DATA from "../dashboard_data.json";
|
// import DATA from "../dashboard_data.json";
|
||||||
|
|
||||||
const DATA_URL =
|
const DATA_URL =
|
||||||
|
@ -50,12 +49,24 @@ export type FeedItemType = {
|
||||||
page_id: string,
|
page_id: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EventType = {
|
||||||
|
id: number,
|
||||||
|
title: string,
|
||||||
|
logo: string | null,
|
||||||
|
date_begin: string,
|
||||||
|
date_end: string,
|
||||||
|
description: string,
|
||||||
|
club: string,
|
||||||
|
category_id: number,
|
||||||
|
url: string,
|
||||||
|
};
|
||||||
|
|
||||||
export type FullDashboardType = {
|
export type FullDashboardType = {
|
||||||
today_menu: Array<{[key: string]: {...}}>,
|
today_menu: Array<{[key: string]: {...}}>,
|
||||||
proximo_articles: number,
|
proximo_articles: number,
|
||||||
available_dryers: number,
|
available_dryers: number,
|
||||||
available_washers: number,
|
available_washers: number,
|
||||||
today_events: Array<PlanningEventType>,
|
today_events: Array<EventType>,
|
||||||
available_tutorials: number,
|
available_tutorials: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,7 +193,7 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
* @param content
|
* @param content
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
getDashboardEvent(content: Array<PlanningEventType>): React.Node {
|
getDashboardEvent(content: Array<EventType>): React.Node {
|
||||||
const futureEvents = getFutureEvents(content);
|
const futureEvents = getFutureEvents(content);
|
||||||
const displayEvent = getDisplayEvent(futureEvents);
|
const displayEvent = getDisplayEvent(futureEvents);
|
||||||
// const clickPreviewAction = () =>
|
// const clickPreviewAction = () =>
|
||||||
|
|
|
@ -3,60 +3,75 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Avatar, Button, Card, Paragraph, withTheme} from 'react-native-paper';
|
import {Avatar, Button, Card, Paragraph, withTheme} from 'react-native-paper';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import {Linking, View} from 'react-native';
|
import {Linking} from 'react-native';
|
||||||
|
import type {CustomThemeType} from '../../managers/ThemeManager';
|
||||||
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
|
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
|
||||||
import type {CardTitleIconPropsType} from '../../constants/PaperStyles';
|
import type {CardTitleIconPropsType} from '../../constants/PaperStyles';
|
||||||
|
|
||||||
|
type PropsType = {
|
||||||
|
theme: CustomThemeType,
|
||||||
|
};
|
||||||
|
|
||||||
const links = {
|
const links = {
|
||||||
bugsGit: 'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/',
|
bugsMail: `mailto:app@amicale-insat.fr?subject=[BUG] Application CAMPUS
|
||||||
trello: 'https://trello.com/b/RMej49Uq/application-campus-insa',
|
&body=Coucou Arnaud ça bug c'est nul,\n\n
|
||||||
|
Informations sur ton système si tu sais (iOS ou Android, modèle du tel, version):\n\n\n
|
||||||
|
Nature du problème :\n\n\n
|
||||||
|
Étapes pour reproduire ce pb :\n\n\n\n
|
||||||
|
Stp corrige le pb, bien cordialement.`,
|
||||||
|
bugsGit:
|
||||||
|
'https://git.etud.insa-toulouse.fr/vergnet/application-amicale/issues/new',
|
||||||
facebook: 'https://www.facebook.com/campus.insat',
|
facebook: 'https://www.facebook.com/campus.insat',
|
||||||
feedbackMail: `mailto:app@amicale-insat.fr?subject=[FEEDBACK] Application CAMPUS
|
feedbackMail: `mailto:app@amicale-insat.fr?subject=[FEEDBACK] Application CAMPUS
|
||||||
&body=Coucou Arnaud j'ai du feedback\n\n\n\nBien cordialement.`,
|
&body=Coucou Arnaud j'ai du feedback\n\n\n\nBien cordialement.`,
|
||||||
feedbackDiscord: 'https://discord.gg/W8MeTec',
|
feedbackDiscord: 'https://discord.gg/W8MeTec',
|
||||||
};
|
};
|
||||||
|
|
||||||
class FeedbackScreen extends React.Component<null> {
|
class FeedbackScreen extends React.Component<PropsType> {
|
||||||
/**
|
/**
|
||||||
* Gets link buttons
|
* Gets link buttons
|
||||||
*
|
*
|
||||||
|
* @param isBug True if buttons should redirect to bug report methods
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
static getButtons(isFeedback: boolean): React.Node {
|
static getButtons(isBug: boolean): React.Node {
|
||||||
return (
|
return (
|
||||||
<Card.Actions
|
<Card.Actions
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
}}>
|
}}>
|
||||||
{isFeedback ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
flexDirection: 'row',
|
|
||||||
width: '100%',
|
|
||||||
}}>
|
|
||||||
<Button
|
<Button
|
||||||
icon="email"
|
icon="email"
|
||||||
mode="contained"
|
mode="contained"
|
||||||
style={{
|
style={{
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
}}
|
}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
Linking.openURL(links.feedbackMail);
|
Linking.openURL(isBug ? links.bugsMail : links.feedbackMail);
|
||||||
}}>
|
}}>
|
||||||
MAIL
|
MAIL
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
icon={isBug ? 'git' : 'discord'}
|
||||||
|
mode="contained"
|
||||||
|
color={isBug ? '#609927' : '#7289da'}
|
||||||
|
style={{
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginTop: 5,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
Linking.openURL(isBug ? links.bugsGit : links.feedbackDiscord);
|
||||||
|
}}>
|
||||||
|
{isBug ? 'GITEA' : 'Discord'}
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
icon="facebook"
|
icon="facebook"
|
||||||
mode="contained"
|
mode="contained"
|
||||||
color="#2e88fe"
|
color="#2e88fe"
|
||||||
style={{
|
style={{
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
}}
|
}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
@ -64,69 +79,34 @@ class FeedbackScreen extends React.Component<null> {
|
||||||
}}>
|
}}>
|
||||||
Facebook
|
Facebook
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
icon="discord"
|
|
||||||
mode="contained"
|
|
||||||
color="#7289da"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.feedbackDiscord);
|
|
||||||
}}>
|
|
||||||
Discord
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
) : (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
flexDirection: 'row',
|
|
||||||
width: '100%',
|
|
||||||
}}>
|
|
||||||
<Button
|
|
||||||
icon="git"
|
|
||||||
mode="contained"
|
|
||||||
color="#609927"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.bugsGit);
|
|
||||||
}}>
|
|
||||||
GITETUD
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
icon="calendar"
|
|
||||||
mode="contained"
|
|
||||||
color="#026AA7"
|
|
||||||
style={{
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
marginTop: 5,
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
Linking.openURL(links.trello);
|
|
||||||
}}>
|
|
||||||
TRELLO
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</Card.Actions>
|
</Card.Actions>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.Node {
|
render(): React.Node {
|
||||||
|
const {theme} = this.props;
|
||||||
return (
|
return (
|
||||||
<CollapsibleScrollView style={{padding: 5}}>
|
<CollapsibleScrollView style={{padding: 5}}>
|
||||||
<Card>
|
<Card>
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={i18n.t('screens.feedback.feedback')}
|
title={i18n.t('screens.feedback.bugs')}
|
||||||
|
subtitle={i18n.t('screens.feedback.bugsSubtitle')}
|
||||||
|
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
||||||
|
<Avatar.Icon size={iconProps.size} icon="bug" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Card.Content>
|
||||||
|
<Paragraph>{i18n.t('screens.feedback.bugsDescription')}</Paragraph>
|
||||||
|
<Paragraph style={{color: theme.colors.primary}}>
|
||||||
|
{i18n.t('screens.feedback.contactMeans')}
|
||||||
|
</Paragraph>
|
||||||
|
</Card.Content>
|
||||||
|
{FeedbackScreen.getButtons(true)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card style={{marginTop: 20, marginBottom: 10}}>
|
||||||
|
<Card.Title
|
||||||
|
title={i18n.t('screens.feedback.title')}
|
||||||
subtitle={i18n.t('screens.feedback.feedbackSubtitle')}
|
subtitle={i18n.t('screens.feedback.feedbackSubtitle')}
|
||||||
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
||||||
<Avatar.Icon size={iconProps.size} icon="comment" />
|
<Avatar.Icon size={iconProps.size} icon="comment" />
|
||||||
|
@ -137,19 +117,6 @@ class FeedbackScreen extends React.Component<null> {
|
||||||
{i18n.t('screens.feedback.feedbackDescription')}
|
{i18n.t('screens.feedback.feedbackDescription')}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
{FeedbackScreen.getButtons(true)}
|
|
||||||
<Card.Title
|
|
||||||
title={i18n.t('screens.feedback.contribute')}
|
|
||||||
subtitle={i18n.t('screens.feedback.contributeSubtitle')}
|
|
||||||
left={(iconProps: CardTitleIconPropsType): React.Node => (
|
|
||||||
<Avatar.Icon size={iconProps.size} icon="handshake" />
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Card.Content>
|
|
||||||
<Paragraph>
|
|
||||||
{i18n.t('screens.feedback.contributeDescription')}
|
|
||||||
</Paragraph>
|
|
||||||
</Card.Content>
|
|
||||||
{FeedbackScreen.getButtons(false)}
|
{FeedbackScreen.getButtons(false)}
|
||||||
</Card>
|
</Card>
|
||||||
</CollapsibleScrollView>
|
</CollapsibleScrollView>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {View} from 'react-native';
|
||||||
import {Card} from 'react-native-paper';
|
import {Card} from 'react-native-paper';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import {getDateOnlyString, getTimeOnlyString} from '../../utils/Planning';
|
import {getDateOnlyString, getFormattedEventTime} from '../../utils/Planning';
|
||||||
import DateManager from '../../managers/DateManager';
|
import DateManager from '../../managers/DateManager';
|
||||||
import BasicLoadingScreen from '../../components/Screens/BasicLoadingScreen';
|
import BasicLoadingScreen from '../../components/Screens/BasicLoadingScreen';
|
||||||
import {apiRequest, ERROR_TYPE} from '../../utils/WebData';
|
import {apiRequest, ERROR_TYPE} from '../../utils/WebData';
|
||||||
|
@ -96,9 +96,12 @@ class PlanningDisplayScreen extends React.Component<PropsType, StateType> {
|
||||||
const {navigation} = this.props;
|
const {navigation} = this.props;
|
||||||
const {displayData} = this;
|
const {displayData} = this;
|
||||||
if (displayData == null) return null;
|
if (displayData == null) return null;
|
||||||
let subtitle = getTimeOnlyString(displayData.date_begin);
|
let subtitle = getFormattedEventTime(
|
||||||
|
displayData.date_begin,
|
||||||
|
displayData.date_end,
|
||||||
|
);
|
||||||
const dateString = getDateOnlyString(displayData.date_begin);
|
const dateString = getDateOnlyString(displayData.date_begin);
|
||||||
if (dateString !== null && subtitle != null)
|
if (dateString !== null)
|
||||||
subtitle += ` | ${DateManager.getInstance().getTranslatedDate(
|
subtitle += ` | ${DateManager.getInstance().getTranslatedDate(
|
||||||
dateString,
|
dateString,
|
||||||
)}`;
|
)}`;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
generateEventAgenda,
|
generateEventAgenda,
|
||||||
getCurrentDateString,
|
getCurrentDateString,
|
||||||
getDateOnlyString,
|
getDateOnlyString,
|
||||||
getTimeOnlyString,
|
getFormattedEventTime,
|
||||||
} from '../../utils/Planning';
|
} from '../../utils/Planning';
|
||||||
import CustomAgenda from '../../components/Overrides/CustomAgenda';
|
import CustomAgenda from '../../components/Overrides/CustomAgenda';
|
||||||
import {MASCOT_STYLE} from '../../components/Mascot/Mascot';
|
import {MASCOT_STYLE} from '../../components/Mascot/Mascot';
|
||||||
|
@ -198,7 +198,7 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
|
||||||
<Divider />
|
<Divider />
|
||||||
<List.Item
|
<List.Item
|
||||||
title={item.title}
|
title={item.title}
|
||||||
description={getTimeOnlyString(item.date_begin)}
|
description={getFormattedEventTime(item.date_begin, item.date_end)}
|
||||||
left={(): React.Node => (
|
left={(): React.Node => (
|
||||||
<Avatar.Image
|
<Avatar.Image
|
||||||
source={{uri: item.logo}}
|
source={{uri: item.logo}}
|
||||||
|
@ -215,7 +215,7 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
|
||||||
<Divider />
|
<Divider />
|
||||||
<List.Item
|
<List.Item
|
||||||
title={item.title}
|
title={item.title}
|
||||||
description={getTimeOnlyString(item.date_begin)}
|
description={getFormattedEventTime(item.date_begin, item.date_end)}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import {stringToDate} from './Planning';
|
import {stringToDate} from './Planning';
|
||||||
import type {PlanningEventType} from './Planning';
|
import type {EventType} from '../screens/Home/HomeScreen';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the time limit depending on the current day:
|
* Gets the time limit depending on the current day:
|
||||||
|
@ -20,6 +20,20 @@ export function getTodayEventTimeLimit(): Date {
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the duration (in milliseconds) of an event
|
||||||
|
*
|
||||||
|
* @param event {EventType}
|
||||||
|
* @return {number} The number of milliseconds
|
||||||
|
*/
|
||||||
|
export function getEventDuration(event: EventType): number {
|
||||||
|
const start = stringToDate(event.date_begin);
|
||||||
|
const end = stringToDate(event.date_end);
|
||||||
|
let duration = 0;
|
||||||
|
if (start != null && end != null) duration = end - start;
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets events starting after the limit
|
* Gets events starting after the limit
|
||||||
*
|
*
|
||||||
|
@ -28,11 +42,11 @@ export function getTodayEventTimeLimit(): Date {
|
||||||
* @return {Array<Object>}
|
* @return {Array<Object>}
|
||||||
*/
|
*/
|
||||||
export function getEventsAfterLimit(
|
export function getEventsAfterLimit(
|
||||||
events: Array<PlanningEventType>,
|
events: Array<EventType>,
|
||||||
limit: Date,
|
limit: Date,
|
||||||
): Array<PlanningEventType> {
|
): Array<EventType> {
|
||||||
const validEvents = [];
|
const validEvents = [];
|
||||||
events.forEach((event: PlanningEventType) => {
|
events.forEach((event: EventType) => {
|
||||||
const startDate = stringToDate(event.date_begin);
|
const startDate = stringToDate(event.date_begin);
|
||||||
if (startDate != null && startDate >= limit) {
|
if (startDate != null && startDate >= limit) {
|
||||||
validEvents.push(event);
|
validEvents.push(event);
|
||||||
|
@ -41,19 +55,44 @@ export function getEventsAfterLimit(
|
||||||
return validEvents;
|
return validEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the event with the longest duration in the given array.
|
||||||
|
* If all events have the same duration, return the first in the array.
|
||||||
|
*
|
||||||
|
* @param events
|
||||||
|
*/
|
||||||
|
export function getLongestEvent(events: Array<EventType>): EventType {
|
||||||
|
let longestEvent = events[0];
|
||||||
|
let longestTime = 0;
|
||||||
|
events.forEach((event: EventType) => {
|
||||||
|
const time = getEventDuration(event);
|
||||||
|
if (time > longestTime) {
|
||||||
|
longestTime = time;
|
||||||
|
longestEvent = event;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return longestEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets events that have not yet ended/started
|
* Gets events that have not yet ended/started
|
||||||
*
|
*
|
||||||
* @param events
|
* @param events
|
||||||
*/
|
*/
|
||||||
export function getFutureEvents(
|
export function getFutureEvents(events: Array<EventType>): Array<EventType> {
|
||||||
events: Array<PlanningEventType>,
|
|
||||||
): Array<PlanningEventType> {
|
|
||||||
const validEvents = [];
|
const validEvents = [];
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
events.forEach((event: PlanningEventType) => {
|
events.forEach((event: EventType) => {
|
||||||
const startDate = stringToDate(event.date_begin);
|
const startDate = stringToDate(event.date_begin);
|
||||||
if (startDate != null && startDate > now) validEvents.push(event);
|
const endDate = stringToDate(event.date_end);
|
||||||
|
if (startDate != null) {
|
||||||
|
if (startDate > now) validEvents.push(event);
|
||||||
|
else if (endDate != null) {
|
||||||
|
if (endDate > now || endDate < startDate)
|
||||||
|
// Display event if it ends the following day
|
||||||
|
validEvents.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return validEvents;
|
return validEvents;
|
||||||
}
|
}
|
||||||
|
@ -62,19 +101,23 @@ export function getFutureEvents(
|
||||||
* Gets the event to display in the preview
|
* Gets the event to display in the preview
|
||||||
*
|
*
|
||||||
* @param events
|
* @param events
|
||||||
* @return {PlanningEventType | null}
|
* @return {EventType | null}
|
||||||
*/
|
*/
|
||||||
export function getDisplayEvent(
|
export function getDisplayEvent(events: Array<EventType>): EventType | null {
|
||||||
events: Array<PlanningEventType>,
|
|
||||||
): PlanningEventType | null {
|
|
||||||
let displayEvent = null;
|
let displayEvent = null;
|
||||||
if (events.length > 1) {
|
if (events.length > 1) {
|
||||||
const eventsAfterLimit = getEventsAfterLimit(
|
const eventsAfterLimit = getEventsAfterLimit(
|
||||||
events,
|
events,
|
||||||
getTodayEventTimeLimit(),
|
getTodayEventTimeLimit(),
|
||||||
);
|
);
|
||||||
if (eventsAfterLimit.length > 0) [displayEvent] = eventsAfterLimit;
|
if (eventsAfterLimit.length > 0) {
|
||||||
else [displayEvent] = events;
|
if (eventsAfterLimit.length === 1) [displayEvent] = eventsAfterLimit;
|
||||||
} else if (events.length === 1) [displayEvent] = events;
|
else displayEvent = getLongestEvent(events);
|
||||||
|
} else {
|
||||||
|
displayEvent = getLongestEvent(events);
|
||||||
|
}
|
||||||
|
} else if (events.length === 1) {
|
||||||
|
[displayEvent] = events;
|
||||||
|
}
|
||||||
return displayEvent;
|
return displayEvent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
export type PlanningEventType = {
|
export type PlanningEventType = {
|
||||||
id: number,
|
id: number,
|
||||||
title: string,
|
title: string,
|
||||||
|
logo: string,
|
||||||
date_begin: string,
|
date_begin: string,
|
||||||
|
date_end: string,
|
||||||
|
description: string,
|
||||||
club: string,
|
club: string,
|
||||||
category_id: number,
|
category_id: number,
|
||||||
description: string,
|
|
||||||
place: string,
|
|
||||||
url: string,
|
url: string,
|
||||||
logo: string | null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Regex used to check date string validity
|
// Regex used to check date string validity
|
||||||
|
@ -120,6 +120,50 @@ export function getTimeOnlyString(dateString: string): string | null {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string corresponding to the event start and end times in the following format:
|
||||||
|
*
|
||||||
|
* HH:MM - HH:MM
|
||||||
|
*
|
||||||
|
* If the end date is not specified or is equal to start time, only start time will be shown.
|
||||||
|
*
|
||||||
|
* If the end date is not on the same day, 23:59 will be shown as end time
|
||||||
|
*
|
||||||
|
* @param start Start time in YYYY-MM-DD HH:MM:SS format
|
||||||
|
* @param end End time in YYYY-MM-DD HH:MM:SS format
|
||||||
|
* @return {string} Formatted string or "/ - /" on error
|
||||||
|
*/
|
||||||
|
export function getFormattedEventTime(start: string, end: string): string {
|
||||||
|
let formattedStr = '/ - /';
|
||||||
|
const startDate = stringToDate(start);
|
||||||
|
const endDate = stringToDate(end);
|
||||||
|
|
||||||
|
if (
|
||||||
|
startDate !== null &&
|
||||||
|
endDate !== null &&
|
||||||
|
startDate.getTime() !== endDate.getTime()
|
||||||
|
) {
|
||||||
|
formattedStr = `${String(startDate.getHours()).padStart(2, '0')}:${String(
|
||||||
|
startDate.getMinutes(),
|
||||||
|
).padStart(2, '0')} - `;
|
||||||
|
if (
|
||||||
|
endDate.getFullYear() > startDate.getFullYear() ||
|
||||||
|
endDate.getMonth() > startDate.getMonth() ||
|
||||||
|
endDate.getDate() > startDate.getDate()
|
||||||
|
)
|
||||||
|
formattedStr += '23:59';
|
||||||
|
else
|
||||||
|
formattedStr += `${String(endDate.getHours()).padStart(2, '0')}:${String(
|
||||||
|
endDate.getMinutes(),
|
||||||
|
).padStart(2, '0')}`;
|
||||||
|
} else if (startDate !== null)
|
||||||
|
formattedStr = `${String(startDate.getHours()).padStart(2, '0')}:${String(
|
||||||
|
startDate.getMinutes(),
|
||||||
|
).padStart(2, '0')}`;
|
||||||
|
|
||||||
|
return formattedStr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given description can be considered empty.
|
* Checks if the given description can be considered empty.
|
||||||
* <br>
|
* <br>
|
||||||
|
|