import axios from 'axios'; import { encode as btoa } from 'base-64'; import { format } from 'date-fns'; import React, { createContext, useContext, useEffect, useState } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { SettingsContext } from './SettingsProvider'; import { ThemeButton, ThemeText } from './common/ThemeTypes'; import { useColors } from './common/colors'; import Login from './screens/Login'; import { ToastType, useToast } from './common/ToastProvider'; export const InterfaceContext = createContext(null); const Interface = ({ children }) => { const colors = useColors(); const { showToast, hideToast } = useToast(); const { settings } = useContext(SettingsContext); const [userInformation, setUserInformation] = useState(null); const [baseData, setBaseData] = useState(null); const [loading, setLoading] = useState(true); const [initialLoading, setInitialLoading] = useState(true); const [error, setError] = useState(false); const [errorObject, setErrorObject] = useState(null); const fetchData = async () => { try { setLoading(true) if (settings.requireAuth ? !settings.username : false) throw new InterfaceError("Authentication Required") if (!settings.url) throw new InterfaceError("Invalid URL") const userinformation = await fetchUserInformation(settings.username); const basedata = await fetchBaseData(); setUserInformation(userinformation) setBaseData(basedata) if (!userinformation || !basedata) throw new InterfaceError("Data returned is Null"); setError(false) setInitialLoading(false) } catch (error) { console.error(error); setErrorObject(error); setError(true) } finally { setLoading(false) } } useEffect(() => { fetchData(); }, [settings]); const refresh = () => { fetchData(); }; const axiosInstance = axios.create({ baseURL: settings.url, }); axiosInstance.interceptors.request.use( (config) => { if (!settings.url) { throw new InterfaceError("Invalid URL") } if (settings.requireAuth) { const { username, password } = settings; const token = btoa(`${username}:${password}`); config.headers.Authorization = `Basic ${token}`; } return config; }, (error) => Promise.reject(error) ); const fetchBaseData = async () => { return await requestGet('basedata/'); }; const fetchUserInformation = async (username) => { try { return await requestGet(`userinformation/?username=${username}`, false); } catch (error) { if (error.response.status === 404) { const demoinformation = await requestGet(`demoinformation/`); if (demoinformation) { console.log("Using Demoinformation"); showToast(ToastType.Info, "You are using a DEMOUSER", 5000); } return demoinformation; } console.error("Error fetching user information:", error); return Null; } }; const fetchTimes = async () => { return await requestGet('hours/'); }; const fetchScheduleByWeek = async (type, value, group, week, year) => { const groupparam = type === 'class' && group ? `&group=${group}` : ''; return await requestGet(`schedule/week/?type=${type}&value=${value}${groupparam}&week=${week}&year=${year}`); }; const fetchScheduleByDate = async (type, value, group, date) => { const groupparam = type === 'class' ? `&group=${group}` : ''; return await requestGet(`schedule/date/?type=${type}&value=${value}${groupparam}&date=${format(date, 'yyyy-MM-dd')}`); }; const fetchAppointments = async (date) => { return await requestGet(`appointments/?date=${format(date, 'yyyy-MM-dd')}`); }; const fetchTests = async (type, value, date) => { return await requestGet(`tests/?type=${type}&value=${value}&date=${format(date, 'yyyy-MM-dd')}`); }; const fetchDayTypes = async (from, until) => { return await requestGet(`daytypes/?from=${format(from, 'yyyy-MM-dd')}&until=${format(until, 'yyyy-MM-dd')}`); }; const fetchFreeRooms = async (date, from, until) => { return await requestGet(`freerooms/?date=${format(date, 'yyyy-MM-dd')}&from=${from}&until=${until}`); }; const requestGet = async (url, handleError = true) => { console.log(url) try { const response = await axiosInstance.get(url); if (response.status === 200 && response.data.success === true) { return response.data.data; } else { throw new NetworkError(response.data.message, url); } } catch (error) { if (!handleError) { throw(error); } else if (error.response) { if (error.response.data.message) { throw new NetworkError(error.response.status + ": " + error.response.data.message, url); } else if (error.response.status === 404) { throw new NetworkError('404: URL wurde auf dem Server nicht gefunden', url); } else if (error.response.status === 502) { throw new NetworkError('502: Webservice ist unerreichbar', url); } throw new NetworkError(`${error.response.status}: Ein unbekannter ist auf dem Server aufgetreten`, url); } else if (error.request) { throw new NetworkError('Netzwerkfehler', url); } else { throw new NetworkError(error.message || 'Ein unbekannter fehler ist aufgetreten', url); } } }; const styles = StyleSheet.create({ container: { paddingTop: 30, flex: 1, }, titleBox: { paddingHorizontal: 20, paddingVertical: 10, backgroundColor: colors.backSecondary, }, title: { fontSize: 20, fontWeight: 'bold', }, button: { marginTop: 5, } }) const renderContent = () => { let needsCredentials = settings.requireAuth ? !settings.username : false; if (error && !loading) return ( {!needsCredentials && Fehler beim laden der Daten {errorObject?.message} Neu Versuchen } ) if (!initialLoading) return (children) } return ( {renderContent()} ); }; export default Interface; export class InterfaceError extends Error { constructor(message) { super(message); this.name = "InterfaceError"; } } export class NetworkError extends Error { url: string; constructor(message: string, url: string) { super(message); this.name = "NetworkError"; this.url = url; } }