changed login

This commit is contained in:
2024-09-19 08:46:08 +02:00
parent 5b82862165
commit b63e55de52
3 changed files with 82 additions and 55 deletions

View File

@@ -6,10 +6,9 @@ import Settings from './screens/Settings';
import { ThemeButton, ThemeText } from './common/ThemeTypes'; import { ThemeButton, ThemeText } from './common/ThemeTypes';
import { StyleSheet, Text, View } from 'react-native'; import { StyleSheet, Text, View } from 'react-native';
import { useColors } from './common/colors'; import { useColors } from './common/colors';
import {decode as atob, encode as btoa} from 'base-64' import { decode as atob, encode as btoa } from 'base-64'
import Login from './screens/Login'; import Login from './screens/Login';
let errorObject;
export const InterfaceContext = createContext<any>(null); export const InterfaceContext = createContext<any>(null);
const Interface = ({ children }) => { const Interface = ({ children }) => {
@@ -19,9 +18,12 @@ const Interface = ({ children }) => {
const [baseData, setBaseData] = useState(null); const [baseData, setBaseData] = useState(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [errorObject, setErrorObject] = useState(null);
const fetchData = async () => { const fetchData = async () => {
try { try {
setLoading(true)
if (settings.requireAuth ? !settings.username : false) throw new InterfaceError("Authentication Required")
if (!settings.url) throw new InterfaceError("Invalid URL") if (!settings.url) throw new InterfaceError("Invalid URL")
const userinformation = await fetchUserInformation(settings.username); const userinformation = await fetchUserInformation(settings.username);
const basedata = await fetchBaseData(); const basedata = await fetchBaseData();
@@ -31,7 +33,7 @@ const Interface = ({ children }) => {
setError(false) setError(false)
} catch (error) { } catch (error) {
console.error(error); console.error(error);
errorObject = error; setErrorObject(error);
setError(true) setError(true)
} finally { } finally {
setLoading(false) setLoading(false)
@@ -67,89 +69,88 @@ const Interface = ({ children }) => {
); );
const fetchBaseData = async () => { const fetchBaseData = async () => {
return await requestGet('basedata/'); return await requestGet('basedata/');
}; };
const fetchUserInformation = async (username) => { const fetchUserInformation = async (username) => {
const userinformation = await requestGet(`userinformation/?username=${username}`, false); const userinformation = await requestGet(`userinformation/?username=${username}`, false);
if (!userinformation) { if (!userinformation) {
return await requestGet(`demoinformation/`); return await requestGet(`demoinformation/`);
} }
return userinformation; return userinformation;
}; };
const fetchTimes = async () => { const fetchTimes = async () => {
return await requestGet('hours/'); return await requestGet('hours/');
}; };
const fetchScheduleByWeek = async (type, value, group, week, year) => { const fetchScheduleByWeek = async (type, value, group, week, year) => {
const groupparam = type === 'class' && group ? `&group=${group}` : ''; const groupparam = type === 'class' && group ? `&group=${group}` : '';
return await requestGet(`schedule/week/?type=${type}&value=${value}${groupparam}&week=${week}&year=${year}`); return await requestGet(`schedule/week/?type=${type}&value=${value}${groupparam}&week=${week}&year=${year}`);
}; };
const fetchScheduleByDate = async (type, value, group, date) => { const fetchScheduleByDate = async (type, value, group, date) => {
const groupparam = type === 'class' ? `&group=${group}` : ''; const groupparam = type === 'class' ? `&group=${group}` : '';
return await requestGet(`schedule/date/?type=${type}&value=${value}${groupparam}&date=${format(date, 'yyyy-MM-dd')}`); return await requestGet(`schedule/date/?type=${type}&value=${value}${groupparam}&date=${format(date, 'yyyy-MM-dd')}`);
}; };
const fetchAppointments = async (date) => { const fetchAppointments = async (date) => {
return await requestGet(`appointments/?date=${format(date, 'yyyy-MM-dd')}`); return await requestGet(`appointments/?date=${format(date, 'yyyy-MM-dd')}`);
}; };
const fetchTests = async (type, value, date) => { const fetchTests = async (type, value, date) => {
return await requestGet(`tests/?type=${type}&value=${value}&date=${format(date, 'yyyy-MM-dd')}`); return await requestGet(`tests/?type=${type}&value=${value}&date=${format(date, 'yyyy-MM-dd')}`);
}; };
const fetchDayTypes = async (from, until) => { const fetchDayTypes = async (from, until) => {
return await requestGet(`daytypes/?from=${format(from, 'yyyy-MM-dd')}&until=${format(until, 'yyyy-MM-dd')}`); return await requestGet(`daytypes/?from=${format(from, 'yyyy-MM-dd')}&until=${format(until, 'yyyy-MM-dd')}`);
}; };
const fetchFreeRooms = async (date, from, until) => { const fetchFreeRooms = async (date, from, until) => {
return await requestGet(`freerooms/?date=${format(date, 'yyyy-MM-dd')}&from=${from}&until=${until}`); return await requestGet(`freerooms/?date=${format(date, 'yyyy-MM-dd')}&from=${from}&until=${until}`);
}; };
const requestGet = async (url, handleError = true) => { const requestGet = async (url, handleError = true) => {
console.log(url)
try { try {
const response = await axiosInstance.get(url); const response = await axiosInstance.get(url);
if (response.status === 200 && response.data.success === true) { if (response.status === 200 && response.data.success === true) {
return response.data.data; return response.data.data;
} else { } else {
throw new InterfaceError(response.data.message); throw new NetworkError(response.data.message, url);
} }
} catch (error) { } catch (error) {
if (!handleError) { if (!handleError) {
return null return null
}else if (error.response) { } else if (error.response) {
if (error.response.data.message){ if (error.response.data.message) {
throw new InterfaceError(error.response.status + ": " + error.response.data.message); throw new NetworkError(error.response.status + ": " + error.response.data.message, url);
}else if (error.response.status === 404) { } else if (error.response.status === 404) {
throw new InterfaceError('404: URL wurde auf dem Server nicht gefunden'); throw new NetworkError('404: URL wurde auf dem Server nicht gefunden', url);
} else if (error.response.status === 500) {
throw new InterfaceError('500: Ein unbekannter Fehler ist auf dem Webservice aufgetreten');
} else if (error.response.status === 502) { } else if (error.response.status === 502) {
throw new InterfaceError('502: Webservice ist unerreichbar'); throw new NetworkError('502: Webservice ist unerreichbar', url);
} }
throw new Error(`${error.response.status}: Ein fehler ist auf dem Server aufgetreten`); throw new NetworkError(`${error.response.status}: Ein unbekannter ist auf dem Server aufgetreten`, url);
} else if (error.request) { } else if (error.request) {
throw new InterfaceError('Netzwerkfehler'); throw new NetworkError('Netzwerkfehler', url);
} else { } else {
throw new InterfaceError(error.message || 'Ein unbekannter fehler ist aufgetreten'); throw new NetworkError(error.message || 'Ein unbekannter fehler ist aufgetreten', url);
} }
} }
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
paddingTop: 30, paddingTop: 30,
flex: 1, flex: 1,
backgroundColor: colors.backSecondary,
}, },
titleBox: { titleBox: {
paddingHorizontal: 20, paddingHorizontal: 20,
paddingVertical: 10, paddingVertical: 10,
backgroundColor: colors.backSecondary,
}, },
title: { title: {
fontSize: 20, fontSize: 20,
@@ -161,18 +162,20 @@ const Interface = ({ children }) => {
}) })
const renderContent = () => { const renderContent = () => {
if (error) return ( let needsCredentials = settings.requireAuth ? !settings.username : false;
if (error && !loading) return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.titleBox}> {!needsCredentials &&
<ThemeText style={styles.title}>Fehler beim laden der Daten</ThemeText> <View style={styles.titleBox}>
<ThemeText>{errorObject?.message}</ThemeText> <ThemeText style={styles.title}>Fehler beim laden der Daten</ThemeText>
<ThemeButton style={styles.button} onPress={refresh}><Text>Neu Versuchen</Text></ThemeButton> <ThemeText>{errorObject?.message}</ThemeText>
</View> <ThemeButton style={styles.button} onPress={refresh}><Text>Neu Versuchen</Text></ThemeButton>
</View>
}
<Login /> <Login />
</View> </View>
) )
if (!loading) return (children) if (!loading) return (children)
//return (children)
} }
return ( return (
@@ -189,4 +192,13 @@ export class InterfaceError extends Error {
super(message); super(message);
this.name = "InterfaceError"; this.name = "InterfaceError";
} }
}
export class NetworkError extends Error {
url: string;
constructor(message: string, url: string) {
super(message);
this.name = "NetworkError";
this.url = url;
}
} }

View File

@@ -54,6 +54,13 @@ const Credits = () => {
return ( return (
<> <>
<View
style={{
borderBottomColor: colors.textAccent,
borderBottomWidth: 1,
marginTop: 40,
}}
/>
<View style={[styles.section, { marginTop: 20 }]}> <View style={[styles.section, { marginTop: 20 }]}>
<ThemeText>EDV-Schule Plattling</ThemeText> <ThemeText>EDV-Schule Plattling</ThemeText>
<TouchableOpacity onPress={() => Linking.openURL('https://www.edvschule-plattling.de/impressum')}> <TouchableOpacity onPress={() => Linking.openURL('https://www.edvschule-plattling.de/impressum')}>

View File

@@ -1,15 +1,13 @@
import React, { useState, useEffect, useContext, useRef } from 'react'; import React, { useState, useEffect, useContext, useRef } from 'react';
import { View, Text, ScrollView, Button, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, Animated } from 'react-native'; import { View, Text, ScrollView, Button, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, Animated, Image } from 'react-native';
import { SettingsContext } from '../SettingsProvider'; import { SettingsContext } from '../SettingsProvider';
import { useColors } from '../common/colors'; import { useColors } from '../common/colors';
import ErrorBoundary from 'react-native-error-boundary'; import ErrorBoundary from 'react-native-error-boundary';
import { ThemeSwitch, ThemeText, ThemeTextInput } from '../common/ThemeTypes'; import { ThemeSwitch, ThemeText, ThemeTextInput } from '../common/ThemeTypes';
import { ToastType, useToast } from '../common/ToastProvider';
import Credits from '../common/Credits'; import Credits from '../common/Credits';
import FontAwesome5 from '@expo/vector-icons/FontAwesome5'; import FontAwesome5 from '@expo/vector-icons/FontAwesome5';
const Login = () => { const Login = () => {
const { showToast, hideToast } = useToast();
const colors = useColors(); const colors = useColors();
const { settings, updateSettings } = useContext(SettingsContext); const { settings, updateSettings } = useContext(SettingsContext);
@@ -50,7 +48,6 @@ const Login = () => {
darkTheme: isDarkMode, darkTheme: isDarkMode,
requireAuth, requireAuth,
}); });
hideToast();
} catch (error) { } catch (error) {
console.error('Error updating settings:', error); console.error('Error updating settings:', error);
Alert.alert('Error', 'Failed to save settings.'); Alert.alert('Error', 'Failed to save settings.');
@@ -61,7 +58,6 @@ const Login = () => {
const handleChange = (setter) => (value) => { const handleChange = (setter) => (value) => {
setter(value); setter(value);
showToast(ToastType.Warn, 'Ungespeicherte Änderungen');
}; };
const toggleAdvancedSettings = () => { const toggleAdvancedSettings = () => {
@@ -113,10 +109,11 @@ const Login = () => {
height: '100%', height: '100%',
}, },
arrowContainer: { arrowContainer: {
display: 'flex',
justifyContent: 'center',
marginTop: 20, marginTop: 20,
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'flex-start',
}, },
advancedButtonText: { advancedButtonText: {
marginLeft: 8, marginLeft: 8,
@@ -126,11 +123,23 @@ const Login = () => {
advancedSection: { advancedSection: {
overflow: 'hidden', overflow: 'hidden',
}, },
logo: {
width: 100,
height: 100,
},
logoContainer: {
marginTop: 10,
display: 'flex',
alignItems: 'center',
},
}); });
return ( return (
<ErrorBoundary> <ErrorBoundary>
<ScrollView style={[styles.container, { backgroundColor: colors.backPrimary }]}> <ScrollView style={[styles.container, { backgroundColor: colors.backPrimary }]}>
<View style={[styles.section, styles.logoContainer]}>
<Image style={styles.logo} source={require('../assets/favicon.png')} />
</View>
<View style={styles.section}> <View style={styles.section}>
<ThemeText style={styles.label}>Benutzername</ThemeText> <ThemeText style={styles.label}>Benutzername</ThemeText>
<ThemeTextInput <ThemeTextInput
@@ -180,7 +189,6 @@ const Login = () => {
</View> </View>
</View> </View>
</Animated.View> </Animated.View>
<Credits /> <Credits />
</ScrollView> </ScrollView>
</ErrorBoundary> </ErrorBoundary>