feat: fix typescript and eslint errors

This commit is contained in:
Arnaud Vergnet 2021-09-12 18:33:18 +02:00
parent d3e94ac9b3
commit 764296708c
39 changed files with 302 additions and 214 deletions

22
App.tsx
View file

@ -50,6 +50,7 @@ import MainApp from './src/screens/MainApp';
import LoginProvider from './src/components/providers/LoginProvider';
import { retrieveLoginToken } from './src/utils/loginToken';
import { setupNotifications } from './src/utils/Notifications';
import { TabRoutes } from './src/navigation/TabNavigator';
// Native optimizations https://reactnavigation.org/docs/react-native-screens
// Crashes app when navigating away from webview on android 9+
@ -76,11 +77,9 @@ type StateType = {
};
export default class App extends React.Component<{}, StateType> {
navigatorRef: { current: null | NavigationContainerRef };
navigatorRef: { current: null | NavigationContainerRef<any> };
defaultHomeRoute: string | undefined;
defaultHomeData: { [key: string]: string } | undefined;
defaultData?: ParsedUrlDataType;
urlHandler: URLHandler;
@ -97,8 +96,7 @@ export default class App extends React.Component<{}, StateType> {
loginToken: undefined,
};
this.navigatorRef = React.createRef();
this.defaultHomeRoute = undefined;
this.defaultHomeData = undefined;
this.defaultData = undefined;
this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL);
this.urlHandler.listen();
setSafeBounceHeight(Platform.OS === 'ios' ? 100 : 20);
@ -112,8 +110,7 @@ export default class App extends React.Component<{}, StateType> {
* @param parsedData The data parsed from the url
*/
onInitialURLParsed = (parsedData: ParsedUrlDataType) => {
this.defaultHomeRoute = parsedData.route;
this.defaultHomeData = parsedData.data;
this.defaultData = parsedData;
};
/**
@ -126,9 +123,9 @@ export default class App extends React.Component<{}, StateType> {
// Navigate to nested navigator and pass data to the index screen
const nav = this.navigatorRef.current;
if (nav != null) {
nav.navigate('home', {
screen: 'index',
params: { nextScreen: parsedData.route, data: parsedData.data },
nav.navigate(TabRoutes.Home, {
nextScreen: parsedData.route,
data: parsedData.data,
});
}
};
@ -213,8 +210,7 @@ export default class App extends React.Component<{}, StateType> {
<LoginProvider initialToken={this.state.loginToken}>
<MainApp
ref={this.navigatorRef}
defaultHomeData={this.defaultHomeData}
defaultHomeRoute={this.defaultHomeRoute}
defaultData={this.defaultData}
/>
</LoginProvider>
</MascotPreferencesProvider>

View file

@ -4,6 +4,7 @@ import i18n from 'i18n-js';
import { FlatList, StyleSheet } from 'react-native';
import { ProfileClubType } from '../../../screens/Amicale/ProfileScreen';
import { useNavigation } from '@react-navigation/core';
import { MainRoutes } from '../../../navigation/MainNavigator';
type Props = {
clubs?: Array<ProfileClubType>;
@ -26,7 +27,10 @@ export default function ProfileClubCard(props: Props) {
const getClubListItem = ({ item }: { item: ProfileClubType }) => {
const onPress = () =>
navigation.navigate('club-information', { clubId: item.id });
navigation.navigate(MainRoutes.ClubInformation, {
type: 'id',
clubId: item.id,
});
let description = i18n.t('screens.profile.isMember');
let icon = (leftProps: {
color: string;

View file

@ -12,6 +12,7 @@ import {
import Urls from '../../../constants/Urls';
import { ProfileDataType } from '../../../screens/Amicale/ProfileScreen';
import i18n from 'i18n-js';
import { MainRoutes } from '../../../navigation/MainNavigator';
type Props = {
profile?: ProfileDataType;
@ -93,7 +94,7 @@ export default function ProfilePersonalCard(props: Props) {
icon="account-edit"
mode="contained"
onPress={() => {
navigation.navigate('website', {
navigation.navigate(MainRoutes.Website, {
host: Urls.websites.amicale,
path: profile?.link,
title: i18n.t('screens.websites.amicale'),

View file

@ -6,6 +6,7 @@ import i18n from 'i18n-js';
import { StyleSheet } from 'react-native';
import CardList from '../../Lists/CardList/CardList';
import { getAmicaleServices, SERVICES_KEY } from '../../../utils/Services';
import { MainRoutes } from '../../../navigation/MainNavigator';
type Props = {
firstname?: string;
@ -51,9 +52,11 @@ function ProfileWelcomeCard(props: Props) {
<Divider />
<Paragraph>{i18n.t('screens.profile.welcomeDescription')}</Paragraph>
<CardList
dataset={getAmicaleServices(navigation.navigate, true, [
SERVICES_KEY.PROFILE,
])}
dataset={getAmicaleServices(
(route) => navigation.navigate(route),
true,
[SERVICES_KEY.PROFILE]
)}
isHorizontal={true}
/>
<Paragraph>{i18n.t('screens.profile.welcomeFeedback')}</Paragraph>
@ -63,7 +66,7 @@ function ProfileWelcomeCard(props: Props) {
icon="bug"
mode="contained"
onPress={() => {
navigation.navigate('feedback');
navigation.navigate(MainRoutes.Feedback);
}}
style={styles.editButton}
>

View file

@ -24,6 +24,7 @@ import * as Animatable from 'react-native-animatable';
import { TAB_BAR_HEIGHT } from '../Tabbar/CustomTabBar';
import { useNavigation } from '@react-navigation/core';
import { useCollapsible } from '../../context/CollapsibleContext';
import { MainRoutes } from '../../navigation/MainNavigator';
type Props = {
onPress: (action: string, data?: string) => void;
@ -138,7 +139,7 @@ function PlanexBottomBar(props: Props) {
>
<FAB
icon={'account-clock'}
onPress={() => navigation.navigate('group-select')}
onPress={() => navigation.navigate(MainRoutes.GroupSelect)}
/>
</Animatable.View>
</View>

View file

@ -22,6 +22,7 @@ import { List } from 'react-native-paper';
import { StyleSheet, View } from 'react-native';
import i18n from 'i18n-js';
import { useNavigation } from '@react-navigation/native';
import { MainRoutes } from '../../navigation/MainNavigator';
const styles = StyleSheet.create({
item: {
@ -53,7 +54,7 @@ function ActionsDashBoardItem() {
icon="chevron-right"
/>
)}
onPress={(): void => navigation.navigate('feedback')}
onPress={(): void => navigation.navigate(MainRoutes.Feedback)}
style={styles.item}
/>
</View>

View file

@ -30,6 +30,7 @@ import type { NewsSourceType } from '../../constants/NewsSourcesConstants';
import ImageGalleryButton from '../Media/ImageGalleryButton';
import { useNavigation } from '@react-navigation/native';
import GENERAL_STYLES from '../../constants/Styles';
import { MainRoutes } from '../../navigation/MainNavigator';
type PropsType = {
item: FeedItemType;
@ -67,7 +68,7 @@ const styles = StyleSheet.create({
function FeedItem(props: PropsType) {
const navigation = useNavigation();
const onPress = () => {
navigation.navigate('feed-information', {
navigation.navigate(MainRoutes.FeedInformation, {
data: item,
date: getFormattedDate(props.item.time),
});

View file

@ -29,6 +29,7 @@ import {
import { StyleSheet } from 'react-native';
import GENERAL_STYLES from '../../../constants/Styles';
import { useNavigation } from '@react-navigation/native';
import { MainRoutes } from '../../../navigation/MainNavigator';
type PropsType = {
userDeviceRentDates: [string, string] | null;
@ -56,14 +57,14 @@ function EquipmentListItem(props: PropsType) {
let onPress;
if (isRented) {
onPress = () => {
navigation.navigate('equipment-confirm', {
navigation.navigate(MainRoutes.EquipmentConfirm, {
item,
dates: userDeviceRentDates,
});
};
} else {
onPress = () => {
navigation.navigate('equipment-rent', { item });
navigation.navigate(MainRoutes.EquipmentRent, { item });
};
}

View file

@ -22,6 +22,7 @@ import { TouchableRipple } from 'react-native-paper';
import { Image } from 'react-native-animatable';
import { useNavigation } from '@react-navigation/native';
import { StyleSheet, ViewStyle } from 'react-native';
import { MainRoutes } from '../../navigation/MainNavigator';
type PropsType = {
images: Array<{ url: string }>;
@ -39,7 +40,7 @@ function ImageGalleryButton(props: PropsType) {
const navigation = useNavigation();
const onPress = () => {
navigation.navigate('gallery', { images: props.images });
navigation.navigate(MainRoutes.Gallery, { images: props.images });
};
return (

View file

@ -30,7 +30,8 @@ const PROXIMO_ENDPOINT = STUDENT_SERVER + '~proximo/v2/api/';
const PROXIMO_IMAGES_ENDPOINT =
STUDENT_SERVER + '~proximo/api_proximo/storage/app/public/';
const APP_IMAGES_ENDPOINT = STUDENT_SERVER + '~amicale_app/images/';
const PROXIWASH_ENDPOINT = 'https://www.proxiwash.com/weblaverie/ma-laverie-2?s=';
const PROXIWASH_ENDPOINT =
'https://www.proxiwash.com/weblaverie/ma-laverie-2?s=';
export default {
amicale: {

View file

@ -147,10 +147,10 @@ export function useCurrentDashboard() {
};
const allDatasets = [
...getAmicaleServices(navigation.navigate, isLoggedIn),
...getStudentServices(navigation.navigate),
...getINSAServices(navigation.navigate),
...getSpecialServices(navigation.navigate),
...getAmicaleServices((route) => navigation.navigate(route), isLoggedIn),
...getStudentServices((route) => navigation.navigate(route)),
...getINSAServices((route) => navigation.navigate(route)),
...getSpecialServices((route) => navigation.navigate(route)),
];
return {
currentDashboard: allDatasets.filter((item) =>

View file

@ -24,7 +24,7 @@ import SettingsScreen from '../screens/Other/Settings/SettingsScreen';
import AboutScreen from '../screens/About/AboutScreen';
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
import DebugScreen from '../screens/About/DebugScreen';
import TabNavigator from './TabNavigator';
import TabNavigator, { TabRoutes } from './TabNavigator';
import GameMainScreen from '../screens/Game/screens/GameMainScreen';
import VoteScreen from '../screens/Amicale/VoteScreen';
import LoginScreen from '../screens/Amicale/LoginScreen';
@ -33,7 +33,10 @@ import ProximoMainScreen from '../screens/Services/Proximo/ProximoMainScreen';
import ProximoListScreen from '../screens/Services/Proximo/ProximoListScreen';
import ProximoAboutScreen from '../screens/Services/Proximo/ProximoAboutScreen';
import ProfileScreen from '../screens/Amicale/ProfileScreen';
import ClubListScreen from '../screens/Amicale/Clubs/ClubListScreen';
import ClubListScreen, {
ClubCategoryType,
ClubType,
} from '../screens/Amicale/Clubs/ClubListScreen';
import ClubAboutScreen from '../screens/Amicale/Clubs/ClubAboutScreen';
import ClubDisplayScreen from '../screens/Amicale/Clubs/ClubDisplayScreen';
import BugReportScreen from '../screens/Other/FeedbackScreen';
@ -60,6 +63,10 @@ import FeedItemScreen from '../screens/Home/FeedItemScreen';
import GroupSelectionScreen from '../screens/Planex/GroupSelectionScreen';
import ServicesSectionScreen from '../screens/Services/ServicesSectionScreen';
import AmicaleContactScreen from '../screens/Amicale/AmicaleContactScreen';
import { FeedItemType } from '../screens/Home/HomeScreen';
import { PlanningEventType } from '../utils/Planning';
import { ServiceCategoryType } from '../utils/Services';
import { ParsedUrlDataType } from '../utils/URLHandler';
export enum MainRoutes {
Main = 'main',
@ -77,6 +84,7 @@ export enum MainRoutes {
Proximo = 'proximo',
ProximoList = 'proximo-list',
ProximoAbout = 'proximo-about',
ProxiwashAbout = 'proxiwash-about',
Profile = 'profile',
ClubList = 'club-list',
ClubInformation = 'club-information',
@ -87,28 +95,72 @@ export enum MainRoutes {
Vote = 'vote',
Feedback = 'feedback',
Website = 'website',
PlanningInformation = 'planning-information',
Scanner = 'scanner',
FeedInformation = 'feed-information',
GroupSelect = 'group-select',
ServicesSection = 'services-section',
AmicaleContact = 'amicale-contact',
}
type DefaultParams = { [key in MainRoutes]: object | undefined };
type DefaultParams = { [key in MainRoutes]: object | undefined } & {
[key in TabRoutes]: object | undefined;
};
export type FullParamsList = DefaultParams & {
'login': { nextScreen: string };
'equipment-confirm': {
export type MainStackParamsList = DefaultParams & {
[MainRoutes.Login]: { nextScreen: string };
[MainRoutes.EquipmentConfirm]: {
item?: DeviceType;
dates: [string, string];
};
'equipment-rent': { item?: DeviceType };
'gallery': { images: Array<{ url: string }> };
[MainRoutes.EquipmentRent]: { item?: DeviceType };
[MainRoutes.Gallery]: { images: Array<{ url: string }> };
[MainRoutes.ProximoList]: {
shouldFocusSearchBar: boolean;
category: number;
};
[MainRoutes.ClubInformation]: ClubInformationScreenParams;
[MainRoutes.Website]: {
host: string;
path?: string;
title: string;
};
[MainRoutes.FeedInformation]: {
data: FeedItemType;
date: string;
};
[MainRoutes.PlanningInformation]: PlanningInformationScreenParams;
[MainRoutes.ServicesSection]: {
data: ServiceCategoryType;
};
};
// Don't know why but TS is complaining without this
// See: https://stackoverflow.com/questions/63652687/interface-does-not-satisfy-the-constraint-recordstring-object-undefined
export type MainStackParamsList = FullParamsList &
Record<string, object | undefined>;
export type ClubInformationScreenParams =
| {
type: 'full';
data: ClubType;
categories: Array<ClubCategoryType>;
}
| {
type: 'id';
clubId: number;
};
export type PlanningInformationScreenParams =
| {
type: 'full';
data: PlanningEventType;
}
| {
type: 'id';
eventId: number;
};
declare global {
namespace ReactNavigation {
interface RootParamList extends MainStackParamsList {}
}
}
const MainStack = createStackNavigator<MainStackParamsList>();
@ -312,41 +364,41 @@ function getRegularScreens(createTabNavigator: () => React.ReactElement) {
}}
/>
<MainStack.Screen
name={'proxiwash-about'}
name={MainRoutes.ProxiwashAbout}
component={ProxiwashAboutScreen}
options={{ title: i18n.t('screens.proxiwash.title') }}
/>
<MainStack.Screen
name={'planning-information'}
name={MainRoutes.PlanningInformation}
component={PlanningDisplayScreen}
options={{ title: i18n.t('screens.planning.eventDetails') }}
/>
<MainStack.Screen
name={'scanner'}
name={MainRoutes.Scanner}
component={ScannerScreen}
options={{ title: i18n.t('screens.scanner.title') }}
/>
<MainStack.Screen
name={'feed-information'}
name={MainRoutes.FeedInformation}
component={FeedItemScreen}
options={{
title: i18n.t('screens.home.feed'),
}}
/>
<MainStack.Screen
name={'group-select'}
name={MainRoutes.GroupSelect}
component={GroupSelectionScreen}
options={{
title: '',
}}
/>
<MainStack.Screen
name={'services-section'}
name={MainRoutes.ServicesSection}
component={ServicesSectionScreen}
options={{ title: 'SECTION' }}
/>
<MainStack.Screen
name={'amicale-contact'}
name={MainRoutes.AmicaleContact}
component={AmicaleContactScreen}
options={{ title: i18n.t('screens.amicaleAbout.title') }}
/>
@ -363,7 +415,9 @@ function MainStackComponent(props: {
return (
<MainStack.Navigator
initialRouteName={showIntro ? MainRoutes.Intro : MainRoutes.Main}
headerMode={'float'}
screenOptions={{
headerMode: 'float',
}}
>
{showIntro ? getIntroScreens() : getRegularScreens(createTabNavigator)}
{isloggedIn ? getAmicaleScreens() : null}
@ -372,8 +426,7 @@ function MainStackComponent(props: {
}
type PropsType = {
defaultHomeRoute?: string;
defaultHomeData?: { [key: string]: string };
defaultData?: ParsedUrlDataType;
};
function MainNavigator(props: PropsType) {
@ -395,7 +448,5 @@ function MainNavigator(props: PropsType) {
export default React.memo(
MainNavigator,
(pp: PropsType, np: PropsType) =>
pp.defaultHomeRoute === np.defaultHomeRoute &&
pp.defaultHomeData === np.defaultHomeData
(pp: PropsType, np: PropsType) => pp.defaultData === np.defaultData
);

View file

@ -36,6 +36,7 @@ import {
getPreferenceString,
GeneralPreferenceKeys,
} from '../utils/asyncStorage';
import { ParsedUrlDataType } from '../utils/URLHandler';
const styles = StyleSheet.create({
header: {
@ -51,25 +52,24 @@ const styles = StyleSheet.create({
},
});
export enum TabRoutes {
Services = 'services',
Proxiwash = 'proxiwash',
Home = 'home',
Planning = 'events',
Planex = 'planex',
}
type DefaultParams = { [key in TabRoutes]: object | undefined };
export type FullParamsList = DefaultParams & {
[TabRoutes.Home]: {
nextScreen: string;
data: Record<string, object | undefined>;
};
export type TabStackParamsList = DefaultParams & {
[TabRoutes.Home]: ParsedUrlDataType;
};
// Don't know why but TS is complaining without this
// See: https://stackoverflow.com/questions/63652687/interface-does-not-satisfy-the-constraint-recordstring-object-undefined
export type TabStackParamsList = FullParamsList &
Record<string, object | undefined>;
const Tab = createBottomTabNavigator<TabStackParamsList>();
type PropsType = {
defaultHomeRoute?: string;
defaultHomeData?: { [key: string]: string };
defaultData?: ParsedUrlDataType;
};
const ICONS: {
@ -111,15 +111,6 @@ function TabNavigator(props: PropsType) {
} else {
defaultRoute = defaultRoute.toLowerCase();
}
let params;
if (props.defaultHomeRoute) {
params = {
data: props.defaultHomeData,
nextScreen: props.defaultHomeRoute,
shouldOpen: true,
};
}
const { colors } = useTheme();
const LABELS: {
@ -133,23 +124,23 @@ function TabNavigator(props: PropsType) {
};
return (
<Tab.Navigator
initialRouteName={defaultRoute}
initialRouteName={defaultRoute as TabRoutes}
tabBar={(tabProps) => (
<CustomTabBar {...tabProps} labels={LABELS} icons={ICONS} />
)}
>
<Tab.Screen
name={'services'}
name={TabRoutes.Services}
component={WebsitesHomeScreen}
options={{ title: i18n.t('screens.services.title') }}
/>
<Tab.Screen
name={'proxiwash'}
name={TabRoutes.Proxiwash}
component={ProxiwashScreen}
options={{ title: i18n.t('screens.proxiwash.title') }}
/>
<Tab.Screen
name={'home'}
name={TabRoutes.Home}
component={HomeScreen}
options={{
title: i18n.t('screens.home.title'),
@ -176,15 +167,15 @@ function TabNavigator(props: PropsType) {
</View>
),
}}
initialParams={params}
initialParams={props.defaultData}
/>
<Tab.Screen
name={'events'}
name={TabRoutes.Planning}
component={PlanningScreen}
options={{ title: i18n.t('screens.planning.title') }}
/>
<Tab.Screen
name={'planex'}
name={TabRoutes.Planex}
component={PlanexScreen}
options={{
title: i18n.t('screens.planex.title'),
@ -196,15 +187,5 @@ function TabNavigator(props: PropsType) {
export default React.memo(
TabNavigator,
(pp: PropsType, np: PropsType) =>
pp.defaultHomeRoute === np.defaultHomeRoute &&
pp.defaultHomeData === np.defaultHomeData
(pp: PropsType, np: PropsType) => pp.defaultData === np.defaultData
);
export enum TabRoutes {
Services = 'services',
Proxiwash = 'proxiwash',
Home = 'home',
Planning = 'events',
Planex = 'planex',
}

View file

@ -35,6 +35,7 @@ import OptionsDialog from '../../components/Dialogs/OptionsDialog';
import type { OptionsDialogButtonType } from '../../components/Dialogs/OptionsDialog';
import GENERAL_STYLES from '../../constants/Styles';
import Urls from '../../constants/Urls';
import { MainRoutes } from '../../navigation/MainNavigator';
const APP_LOGO = require('../../../assets/android.icon.round.png');
@ -179,7 +180,7 @@ class AboutScreen extends React.Component<PropsType, StateType> {
{
onPressCallback: () => {
const { navigation } = this.props;
navigation.navigate('feedback');
navigation.navigate(MainRoutes.Feedback);
},
icon: 'bug',
text: i18n.t('screens.feedback.homeButtonTitle'),
@ -236,7 +237,7 @@ class AboutScreen extends React.Component<PropsType, StateType> {
{
onPressCallback: () => {
const { navigation } = this.props;
navigation.navigate('dependencies');
navigation.navigate(MainRoutes.Dependencies);
},
icon: 'developer-board',
text: i18n.t('screens.about.libs'),
@ -275,7 +276,7 @@ class AboutScreen extends React.Component<PropsType, StateType> {
{
onPressCallback: () => {
const { navigation } = this.props;
navigation.navigate('feedback');
navigation.navigate(MainRoutes.Feedback);
},
icon: 'hand-pointing-right',
text: i18n.t('screens.about.user.you'),

View file

@ -38,16 +38,13 @@ import { useFocusEffect } from '@react-navigation/core';
import { useCallback } from 'react';
import { useNavigation } from '@react-navigation/native';
import { useAuthenticatedRequest } from '../../../context/loginContext';
import { StackScreenProps } from '@react-navigation/stack';
import {
MainRoutes,
MainStackParamsList,
} from '../../../navigation/MainNavigator';
type Props = {
route: {
params?: {
data?: ClubType;
categories?: Array<ClubCategoryType>;
clubId?: number;
};
};
};
type Props = StackScreenProps<MainStackParamsList, MainRoutes.ClubInformation>;
type ResponseType = ClubType;
@ -94,18 +91,19 @@ function ClubDisplayScreen(props: Props) {
const theme = useTheme();
const [displayData, setDisplayData] = useState<ClubType | undefined>();
const [categories, setCategories] =
useState<Array<ClubCategoryType> | undefined>();
const [categories, setCategories] = useState<
Array<ClubCategoryType> | undefined
>();
const [clubId, setClubId] = useState<number | undefined>();
useFocusEffect(
useCallback(() => {
if (props.route.params?.data && props.route.params?.categories) {
if (props.route.params.type === 'full') {
setDisplayData(props.route.params.data);
setCategories(props.route.params.categories);
setClubId(props.route.params.data.id);
} else {
const id = props.route.params?.clubId;
const id = props.route.params.clubId;
setClubId(id ? id : 0);
}
}, [props.route.params])

View file

@ -33,6 +33,7 @@ import MaterialHeaderButtons, {
import WebSectionList from '../../../components/Screens/WebSectionList';
import { useNavigation } from '@react-navigation/native';
import { useAuthenticatedRequest } from '../../../context/loginContext';
import { MainRoutes } from '../../../navigation/MainNavigator';
export type ClubCategoryType = {
id: number;
@ -80,7 +81,7 @@ function ClubListScreen() {
<Item
title="main"
iconName="information"
onPress={() => navigation.navigate('club-about')}
onPress={() => navigation.navigate(MainRoutes.ClubAbout)}
/>
</MaterialHeaderButtons>
);
@ -108,7 +109,8 @@ function ClubListScreen() {
* @param item The article pressed
*/
const onListItemPress = (item: ClubType) => {
navigation.navigate('club-information', {
navigation.navigate(MainRoutes.ClubInformation, {
type: 'full',
data: item,
categories: categories.current,
});

View file

@ -31,12 +31,15 @@ import i18n from 'i18n-js';
import { getRelativeDateString } from '../../../utils/EquipmentBooking';
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
import { StackScreenProps } from '@react-navigation/stack';
import { MainStackParamsList } from '../../../navigation/MainNavigator';
import {
MainRoutes,
MainStackParamsList,
} from '../../../navigation/MainNavigator';
import GENERAL_STYLES from '../../../constants/Styles';
type EquipmentConfirmScreenNavigationProp = StackScreenProps<
MainStackParamsList,
'equipment-confirm'
MainRoutes.EquipmentConfirm
>;
type Props = EquipmentConfirmScreenNavigationProp;

View file

@ -60,15 +60,15 @@ const styles = StyleSheet.create({
function EquipmentListScreen() {
const userRents = useRef<undefined | Array<RentedDeviceType>>();
const [mascotDialogVisible, setMascotDialogVisible] =
useState<undefined | boolean>(undefined);
const [mascotDialogVisible, setMascotDialogVisible] = useState<
undefined | boolean
>(undefined);
const requestAll =
useAuthenticatedRequest<{ devices: Array<DeviceType> }>('location/all');
const requestOwn =
useAuthenticatedRequest<{
locations: Array<RentedDeviceType>;
}>('location/my');
const requestOwn = useAuthenticatedRequest<{
locations: Array<RentedDeviceType>;
}>('location/my');
const getRenderItem = ({ item }: { item: DeviceType }) => {
return (

View file

@ -42,7 +42,10 @@ import {
isEquipmentAvailable,
} from '../../../utils/EquipmentBooking';
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
import { MainStackParamsList } from '../../../navigation/MainNavigator';
import {
MainRoutes,
MainStackParamsList,
} from '../../../navigation/MainNavigator';
import GENERAL_STYLES from '../../../constants/Styles';
import { ApiRejectType } from '../../../utils/WebData';
import { REQUEST_STATUS } from '../../../utils/Requests';
@ -50,7 +53,7 @@ import { useFocusEffect } from '@react-navigation/core';
import { useNavigation } from '@react-navigation/native';
import { useAuthenticatedRequest } from '../../../context/loginContext';
type Props = StackScreenProps<MainStackParamsList, 'equipment-rent'>;
type Props = StackScreenProps<MainStackParamsList, MainRoutes.EquipmentRent>;
export type MarkedDatesObjectType = {
[key: string]: PeriodMarking;

View file

@ -26,7 +26,10 @@ import ErrorDialog from '../../components/Dialogs/ErrorDialog';
import { MASCOT_STYLE } from '../../components/Mascot/Mascot';
import MascotPopup from '../../components/Mascot/MascotPopup';
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
import { MainStackParamsList } from '../../navigation/MainNavigator';
import {
MainRoutes,
MainStackParamsList,
} from '../../navigation/MainNavigator';
import GENERAL_STYLES from '../../constants/Styles';
import Urls from '../../constants/Urls';
import { ApiRejectType, connectToAmicale } from '../../utils/WebData';
@ -37,15 +40,16 @@ import { TabRoutes } from '../../navigation/TabNavigator';
import { useShouldShowMascot } from '../../context/preferencesContext';
import { useLogin } from '../../context/loginContext';
type Props = StackScreenProps<MainStackParamsList, 'login'>;
type Props = StackScreenProps<MainStackParamsList, MainRoutes.Login>;
function LoginScreen(props: Props) {
const navigation = useNavigation<StackNavigationProp<any>>();
const { setLogin } = useLogin();
const [loading, setLoading] = useState(false);
const [nextScreen, setNextScreen] = useState<string | undefined>(undefined);
const [mascotDialogVisible, setMascotDialogVisible] =
useState<undefined | boolean>(undefined);
const [mascotDialogVisible, setMascotDialogVisible] = useState<
undefined | boolean
>(undefined);
const [currentError, setCurrentError] = useState<ApiRejectType>({
status: REQUEST_STATUS.SUCCESS,
});
@ -58,7 +62,7 @@ function LoginScreen(props: Props) {
);
const onResetPasswordClick = () => {
navigation.navigate('website', {
navigation.navigate(MainRoutes.Website, {
host: Urls.websites.amicale,
path: Urls.amicale.resetPassword,
title: i18n.t('screens.websites.amicale'),

View file

@ -133,8 +133,9 @@ const styles = StyleSheet.create({
*/
export default function VoteScreen() {
const [hasVoted, setHasVoted] = useState(false);
const [mascotDialogVisible, setMascotDialogVisible] =
useState<undefined | boolean>(undefined);
const [mascotDialogVisible, setMascotDialogVisible] = useState<
undefined | boolean
>(undefined);
const datesRequest =
useAuthenticatedRequest<VoteDatesStringType>('elections/dates');

View file

@ -79,13 +79,12 @@ export default function GameMainScreen() {
gameLevel: 0,
});
const [dialogContent, setDialogContent] =
useState<{
dialogTitle: string;
dialogMessage: string;
dialogButtons: Array<OptionsDialogButtonType>;
onDialogDismiss: () => void;
}>();
const [dialogContent, setDialogContent] = useState<{
dialogTitle: string;
dialogMessage: string;
dialogButtons: Array<OptionsDialogButtonType>;
onDialogDismiss: () => void;
}>();
const { preferences, updatePreferences } = usePreferences();

View file

@ -21,7 +21,7 @@ import * as React from 'react';
import { Linking, Image, StyleSheet } from 'react-native';
import { Card, Text } from 'react-native-paper';
import Autolink from 'react-native-autolink';
import { StackNavigationProp } from '@react-navigation/stack';
import { StackScreenProps } from '@react-navigation/stack';
import MaterialHeaderButtons, {
Item,
} from '../../components/Overrides/CustomHeaderButton';
@ -33,11 +33,15 @@ import NewsSourcesConstants, {
AvailablePages,
} from '../../constants/NewsSourcesConstants';
import type { NewsSourceType } from '../../constants/NewsSourcesConstants';
import {
MainRoutes,
MainStackParamsList,
} from '../../navigation/MainNavigator';
type PropsType = {
navigation: StackNavigationProp<any>;
route: { params: { data: FeedItemType; date: string } };
};
type PropsType = StackScreenProps<
MainStackParamsList,
MainRoutes.FeedInformation
>;
const styles = StyleSheet.create({
container: {

View file

@ -154,7 +154,7 @@ function HomeScreen(props: Props) {
useLayoutEffect(() => {
const getHeaderButton = () => {
let onPressLog = () =>
navigation.navigate('login', { nextScreen: 'profile' });
navigation.navigate(MainRoutes.Login, { nextScreen: 'profile' });
let logIcon = 'login';
let logColor = theme.colors.primary;
if (isLoggedIn) {
@ -190,8 +190,8 @@ function HomeScreen(props: Props) {
const handleNavigationParams = () => {
const { route } = props;
if (route.params != null) {
if (route.params.nextScreen != null) {
navigation.navigate(route.params.nextScreen, route.params.data);
if (route.params.route != null) {
navigation.navigate(route.params.route, route.params.data);
// reset params to prevent infinite loop
navigation.dispatch(CommonActions.setParams({ nextScreen: null }));
}
@ -328,7 +328,7 @@ function HomeScreen(props: Props) {
const hideDisconnectDialog = () => setDialogVisible(false);
const openScanner = () => navigation.navigate('scanner');
const openScanner = () => navigation.navigate(MainRoutes.Scanner);
/**
* Creates the dataset to be used in the FlatList

View file

@ -13,13 +13,13 @@ import { Platform, SafeAreaView, View } from 'react-native';
import { useDarkTheme } from '../context/preferencesContext';
import { CustomDarkTheme, CustomWhiteTheme } from '../utils/Themes';
import { setupStatusBar } from '../utils/Utils';
import { ParsedUrlDataType } from '../utils/URLHandler';
type Props = {
defaultHomeRoute?: string;
defaultHomeData?: { [key: string]: string };
defaultData?: ParsedUrlDataType;
};
function MainApp(props: Props, ref?: Ref<NavigationContainerRef>) {
function MainApp(props: Props, ref?: Ref<NavigationContainerRef<any>>) {
const darkTheme = useDarkTheme();
const theme = darkTheme ? CustomDarkTheme : CustomWhiteTheme;
@ -44,10 +44,7 @@ function MainApp(props: Props, ref?: Ref<NavigationContainerRef>) {
>
<SafeAreaView style={GENERAL_STYLES.flex}>
<NavigationContainer theme={theme} ref={ref}>
<MainNavigator
defaultHomeRoute={props.defaultHomeRoute}
defaultHomeData={props.defaultHomeData}
/>
<MainNavigator defaultData={props.defaultData} />
</NavigationContainer>
</SafeAreaView>
</View>

View file

@ -23,11 +23,14 @@ import ImageViewer from 'react-native-image-zoom-viewer';
import { StackNavigationProp, StackScreenProps } from '@react-navigation/stack';
import * as Animatable from 'react-native-animatable';
import { StyleSheet, View } from 'react-native';
import { MainStackParamsList } from '../../navigation/MainNavigator';
import {
MainRoutes,
MainStackParamsList,
} from '../../navigation/MainNavigator';
type ImageGalleryScreenNavigationProp = StackScreenProps<
MainStackParamsList,
'gallery'
MainRoutes.Gallery
>;
type Props = ImageGalleryScreenNavigationProp & {

View file

@ -149,6 +149,7 @@ function DashboardEditScreen() {
return (
<CollapsibleFlatList
//@ts-ignore
data={getCategories(navigation.navigate, isLoggedIn)}
renderItem={getRenderItem}
ListHeaderComponent={getListHeader()}

View file

@ -44,6 +44,7 @@ import {
GeneralPreferenceKeys,
ProxiwashPreferenceKeys,
} from '../../../utils/asyncStorage';
import { MainRoutes } from '../../../navigation/MainNavigator';
const styles = StyleSheet.create({
slider: {
@ -204,7 +205,7 @@ function SettingsScreen() {
};
const getNavigateItem = (
route: string,
route: MainRoutes,
icon: string,
title: string,
subtitle: string,
@ -283,7 +284,7 @@ function SettingsScreen() {
/>
{getStartScreenPicker()}
{getNavigateItem(
'dashboard-edit',
MainRoutes.DashboardEdit,
'view-dashboard',
i18n.t('screens.settings.dashboard'),
i18n.t('screens.settings.dashboardSub')
@ -328,21 +329,21 @@ function SettingsScreen() {
<List.Section>
{isDebugUnlocked
? getNavigateItem(
'debug',
MainRoutes.Debug,
'bug-check',
i18n.t('screens.debug.title'),
''
)
: null}
{getNavigateItem(
'about',
MainRoutes.About,
'information',
i18n.t('screens.about.title'),
i18n.t('screens.about.buttonDesc'),
unlockDebugMode
)}
{getNavigateItem(
'feedback',
MainRoutes.Feedback,
'comment-quote',
i18n.t('screens.feedback.homeButtonTitle'),
i18n.t('screens.feedback.homeButtonSubtitle')

View file

@ -42,6 +42,7 @@ import {
} from '../../utils/asyncStorage';
import { usePlanexPreferences } from '../../context/preferencesContext';
import BasicLoadingScreen from '../../components/Screens/BasicLoadingScreen';
import { MainRoutes } from '../../navigation/MainNavigator';
const styles = StyleSheet.create({
container: {
@ -59,15 +60,14 @@ function PlanexScreen() {
const theme = useTheme();
const { preferences } = usePlanexPreferences();
const [dialogContent, setDialogContent] =
useState<
| undefined
| {
title: string | React.ReactElement;
message: string | React.ReactElement;
color: string;
}
>();
const [dialogContent, setDialogContent] = useState<
| undefined
| {
title: string | React.ReactElement;
message: string | React.ReactElement;
color: string;
}
>();
const [injectJS, setInjectJS] = useState('');
const [loading, setLoading] = useState(true);
@ -106,7 +106,7 @@ function PlanexScreen() {
* Callback used when the user clicks on the navigate to settings button.
* This will hide the banner and open the SettingsScreen
*/
const onGoToSettings = () => navigation.navigate('settings');
const onGoToSettings = () => navigation.navigate(MainRoutes.Settings);
/**
* Sends a FullCalendar action to the web page inside the webview.

View file

@ -21,7 +21,7 @@ import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { Card } from 'react-native-paper';
import i18n from 'i18n-js';
import { StackNavigationProp } from '@react-navigation/stack';
import { StackScreenProps } from '@react-navigation/stack';
import { getDateOnlyString, getTimeOnlyString } from '../../utils/Planning';
import DateManager from '../../managers/DateManager';
import BasicLoadingScreen from '../../components/Screens/BasicLoadingScreen';
@ -33,11 +33,15 @@ import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrol
import type { PlanningEventType } from '../../utils/Planning';
import ImageGalleryButton from '../../components/Media/ImageGalleryButton';
import { API_REQUEST_CODES, REQUEST_STATUS } from '../../utils/Requests';
import {
MainRoutes,
MainStackParamsList,
} from '../../navigation/MainNavigator';
type PropsType = {
navigation: StackNavigationProp<any>;
route: { params: { data: PlanningEventType; id: number; eventId: number } };
};
type PropsType = StackScreenProps<
MainStackParamsList,
MainRoutes.PlanningInformation
>;
type StateType = {
loading: boolean;
@ -78,7 +82,7 @@ class PlanningDisplayScreen extends React.Component<PropsType, StateType> {
constructor(props: PropsType) {
super(props);
if (props.route.params.data != null) {
if (props.route.params.type === 'full') {
this.displayData = props.route.params.data;
this.eventId = this.displayData.id;
this.shouldFetchData = false;

View file

@ -36,6 +36,7 @@ import { MASCOT_STYLE } from '../../components/Mascot/Mascot';
import MascotPopup from '../../components/Mascot/MascotPopup';
import GENERAL_STYLES from '../../constants/Styles';
import Urls from '../../constants/Urls';
import { MainRoutes } from '../../navigation/MainNavigator';
LocaleConfig.locales.fr = {
monthNames: [
@ -217,7 +218,7 @@ class PlanningScreen extends React.Component<PropsType, StateType> {
getRenderItem = (item: PlanningEventType) => {
const { navigation } = this.props;
const onPress = () => {
navigation.navigate('planning-information', {
navigation.navigate(MainRoutes.PlanningInformation, {
data: item,
});
};

View file

@ -61,6 +61,7 @@ import {
} from '../../utils/asyncStorage';
import { useProxiwashPreferences } from '../../context/preferencesContext';
import { useSubsequentEffect } from '../../utils/customHooks';
import { MainRoutes } from '../../navigation/MainNavigator';
const REFRESH_TIME = 1000 * 10; // Refresh every 10 seconds
const LIST_ITEM_HEIGHT = 64;
@ -170,7 +171,7 @@ function ProxiwashScreen() {
<Item
title={'information'}
iconName={'information'}
onPress={() => navigation.navigate('proxiwash-about')}
onPress={() => navigation.navigate(MainRoutes.ProxiwashAbout)}
/>
</MaterialHeaderButtons>
),
@ -494,7 +495,7 @@ function ProxiwashScreen() {
action: {
message: i18n.t('screens.proxiwash.mascotDialog.ok'),
icon: 'cog',
onPress: () => navigation.navigate('settings'),
onPress: () => navigation.navigate(MainRoutes.Settings),
},
cancel: {
message: i18n.t('screens.proxiwash.mascotDialog.cancel'),

View file

@ -123,8 +123,9 @@ function ProximoListScreen(props: Props) {
const [currentSearchString, setCurrentSearchString] = useState('');
const [currentSortMode, setCurrentSortMode] = useState(2);
const [modalCurrentDisplayItem, setModalCurrentDisplayItem] =
useState<React.ReactChild | undefined>();
const [modalCurrentDisplayItem, setModalCurrentDisplayItem] = useState<
React.ReactChild | undefined
>();
const sortModes = [sortPrice, sortPriceReverse, sortName, sortNameReverse];

View file

@ -32,6 +32,7 @@ import { useNavigation } from '@react-navigation/core';
import { useLayoutEffect } from 'react';
import { useCachedProximoCategories } from '../../../context/cacheContext';
import GENERAL_STYLES from '../../../constants/Styles';
import { MainRoutes } from '../../../navigation/MainNavigator';
const LIST_ITEM_HEIGHT = 84;
@ -122,10 +123,10 @@ function ProximoMainScreen() {
shouldFocusSearchBar: true,
category: -1,
};
navigation.navigate('proximo-list', searchScreenData);
navigation.navigate(MainRoutes.ProximoList, searchScreenData);
};
const onPressAboutBtn = () => navigation.navigate('proximo-about');
const onPressAboutBtn = () => navigation.navigate(MainRoutes.ProximoAbout);
const getHeaderButtons = () => {
return (
@ -170,7 +171,8 @@ function ProximoMainScreen() {
? i18n.t('screens.proximo.articles')
: i18n.t('screens.proximo.article')
}`;
const onPress = () => navigation.navigate('proximo-list', dataToSend);
const onPress = () =>
navigation.navigate(MainRoutes.ProximoList, dataToSend);
if (article_number > 0) {
return (
<List.Item

View file

@ -42,6 +42,7 @@ import {
} from '../../utils/Services';
import { useNavigation } from '@react-navigation/native';
import { useLoginState } from '../../context/loginContext';
import { MainRoutes } from '../../navigation/MainNavigator';
const styles = StyleSheet.create({
container: {
@ -62,6 +63,7 @@ function ServicesScreen() {
const theme = useTheme();
const isLoggedIn = useLoginState();
//@ts-ignore
const finalDataset = getCategories(navigation.navigate, isLoggedIn, [
SERVICES_CATEGORIES_KEY.SPECIAL,
]);
@ -72,7 +74,7 @@ function ServicesScreen() {
<Item
title="information"
iconName="information"
onPress={() => navigation.navigate('amicale-contact')}
onPress={() => navigation.navigate(MainRoutes.AmicaleContact)}
/>
</MaterialHeaderButtons>
);
@ -114,7 +116,9 @@ function ServicesScreen() {
return (
<TouchableRipple
style={styles.container}
onPress={() => navigation.navigate('services-section', { data: item })}
onPress={() =>
navigation.navigate(MainRoutes.ServicesSection, { data: item })
}
>
<View>
<Card.Title

View file

@ -18,17 +18,19 @@
*/
import * as React from 'react';
import { Collapsible } from 'react-navigation-collapsible';
import { CommonActions } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { StackScreenProps } from '@react-navigation/stack';
import CardList from '../../components/Lists/CardList/CardList';
import { ServiceCategoryType } from '../../utils/Services';
import {
MainRoutes,
MainStackParamsList,
} from '../../navigation/MainNavigator';
type PropsType = {
navigation: StackNavigationProp<any>;
route: { params: { data: ServiceCategoryType | null } };
collapsibleStack: Collapsible;
};
type PropsType = StackScreenProps<
MainStackParamsList,
MainRoutes.ServicesSection
>;
class ServicesSectionScreen extends React.Component<PropsType> {
finalDataset: null | ServiceCategoryType;

View file

@ -18,15 +18,16 @@
*/
import * as React from 'react';
import { StackNavigationProp } from '@react-navigation/stack';
import { StackScreenProps } from '@react-navigation/stack';
import WebViewScreen from '../../components/Screens/WebViewScreen';
import BasicLoadingScreen from '../../components/Screens/BasicLoadingScreen';
import Urls from '../../constants/Urls';
import {
MainRoutes,
MainStackParamsList,
} from '../../navigation/MainNavigator';
type Props = {
navigation: StackNavigationProp<any>;
route: { params: { host: string; path: string | null; title: string } };
};
type Props = StackScreenProps<MainStackParamsList, MainRoutes.Website>;
type State = {
url: string;

View file

@ -87,8 +87,8 @@ export type ServiceCategoryType = {
};
function getAmicaleOnPress(
route: string,
onPress: (route: string, params?: { [key: string]: any }) => void,
route: MainRoutes,
onPress: (route: MainRoutes, params?: { [key: string]: any }) => void,
isLoggedIn: boolean
) {
if (isLoggedIn) {
@ -99,7 +99,7 @@ function getAmicaleOnPress(
}
export function getAmicaleServices(
onPress: (route: string, params?: { [key: string]: any }) => void,
onPress: (route: MainRoutes, params?: { [key: string]: any }) => void,
isLoggedIn: boolean,
excludedItems?: Array<string>
): Array<ServiceItemType> {
@ -148,7 +148,7 @@ export function getAmicaleServices(
}
export function getStudentServices(
onPress: (route: string, params?: { [key: string]: any }) => void,
onPress: (route: MainRoutes, params?: { [key: string]: any }) => void,
excludedItems?: Array<string>
): Array<ServiceItemType> {
const studentsDataset = [
@ -201,7 +201,7 @@ export function getStudentServices(
}
export function getINSAServices(
onPress: (route: string, params?: { [key: string]: any }) => void,
onPress: (route: MainRoutes, params?: { [key: string]: any }) => void,
excludedItems?: Array<string>
): Array<ServiceItemType> {
const insaDataset = [
@ -274,7 +274,10 @@ export function getINSAServices(
}
export function getSpecialServices(
onPress: (route: string, params?: { [key: string]: any }) => void,
onPress: (
route: MainRoutes | TabRoutes,
params?: { [key: string]: any }
) => void,
excludedItems?: Array<string>
): Array<ServiceItemType> {
const specialDataset = [
@ -301,7 +304,10 @@ export function getSpecialServices(
}
export function getCategories(
onPress: (route: string, params?: { [key: string]: any }) => void,
onPress: (
route: MainRoutes | TabRoutes,
params?: { [key: string]: any }
) => void,
isLoggedIn: boolean,
excludedItems?: Array<string>
): Array<ServiceCategoryType> {

View file

@ -18,10 +18,15 @@
*/
import { Linking } from 'react-native';
import {
ClubInformationScreenParams,
MainRoutes,
PlanningInformationScreenParams,
} from '../navigation/MainNavigator';
export type ParsedUrlDataType = {
route: string;
data: { [key: string]: string };
route: MainRoutes.ClubInformation | MainRoutes.PlanningInformation;
data: ClubInformationScreenParams | PlanningInformationScreenParams;
};
export type ParsedUrlCallbackType = (parsedData: ParsedUrlDataType) => void;
@ -41,10 +46,6 @@ export default class URLHandler {
static EVENT_INFO_URL_PATH = 'event';
static CLUB_INFO_ROUTE = 'club-information';
static EVENT_INFO_ROUTE = 'planning-information';
onInitialURLParsed: ParsedUrlCallbackType;
onDetectURL: ParsedUrlCallbackType;
@ -152,8 +153,11 @@ export default class URLHandler {
const id = parseInt(params.id, 10);
if (!Number.isNaN(id)) {
return {
route: URLHandler.CLUB_INFO_ROUTE,
data: { clubId: id.toString() },
route: MainRoutes.ClubInformation,
data: {
type: 'id',
clubId: id,
},
};
}
}
@ -173,8 +177,11 @@ export default class URLHandler {
const id = parseInt(params.id, 10);
if (!Number.isNaN(id)) {
return {
route: URLHandler.EVENT_INFO_ROUTE,
data: { eventId: id.toString() },
route: MainRoutes.PlanningInformation,
data: {
type: 'id',
eventId: id,
},
};
}
}