180 lines
5.7 KiB
TypeScript
180 lines
5.7 KiB
TypeScript
import React, { useEffect, useState, useContext } from 'react';
|
|
import { ScrollView, StyleSheet, View } from 'react-native';
|
|
import { RefreshControl } from 'react-native-web-refresh-control';
|
|
import ScheduleBuilder from '../common/ScheduleBuilder';
|
|
import { InterfaceContext } from '../Interface';
|
|
import { SettingsContext } from '../SettingsProvider';
|
|
import ErrorBoundary from 'react-native-error-boundary';
|
|
import { useColors } from '../common/colors';
|
|
import ErrorDisplay from '../common/ErrorDisplay';
|
|
import { ThemeText } from '../common/ThemeTypes';
|
|
import { addDays, format } from 'date-fns';
|
|
|
|
let errorObject;
|
|
|
|
const Dashboard = () => {
|
|
const colors = useColors();
|
|
const [scheduleData, setScheduleData] = useState(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState(false);
|
|
const { fetchTimes, fetchScheduleByDate, refreshInterface, userInformation, fetchTests, fetchAppointments } = useContext(InterfaceContext);
|
|
const { settings } = useContext(SettingsContext);
|
|
const [tests, setTests] = useState([]);
|
|
const [appointments, setAppointments] = useState([]);
|
|
|
|
const fetchData = async () => {
|
|
try {
|
|
setLoading(true);
|
|
if (!userInformation) {
|
|
refreshInterface();
|
|
throw new Error("UserInformation is Null");
|
|
}
|
|
const hours = await fetchTimes();
|
|
const date = adjustedDate();
|
|
let type = userInformation.usertype === 'pupil' ? 'class' : 'teacher';
|
|
let value = userInformation.usertype === 'pupil' ? userInformation.classid : userInformation.id;
|
|
const day = await fetchScheduleByDate(type, value, userInformation.group, date);
|
|
const testList = await fetchTests(type, value, new Date());
|
|
const appointmentList = await fetchAppointments(new Date());
|
|
if (!hours || !day || !testList || !appointmentList || !userInformation) throw new Error("Data returned is Null");
|
|
setScheduleData({ hours: hours, days: [day], type: type });
|
|
setTests(testList);
|
|
setAppointments(appointmentList);
|
|
setError(false);
|
|
} catch (error) {
|
|
console.error(error);
|
|
errorObject = error;
|
|
setError(true);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, [settings, userInformation]);
|
|
|
|
const refresh = () => {
|
|
fetchData();
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
display: 'flex',
|
|
flexWrap: 'wrap',
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
},
|
|
sideContainer: {
|
|
padding: 5,
|
|
alignItems: 'center',
|
|
flexDirection: 'column',
|
|
},
|
|
sideSectionContainer: {
|
|
borderColor: '#ccc',
|
|
borderWidth: 1,
|
|
marginBottom: 10,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
width: 130,
|
|
textAlign: 'center',
|
|
},
|
|
boxHeader: {
|
|
fontWeight: 'bold',
|
|
fontSize: 18,
|
|
marginBottom: 10,
|
|
},
|
|
box: {
|
|
backgroundColor: colors.backSecondary,
|
|
padding: 5,
|
|
margin: 5,
|
|
width: 110,
|
|
maxHeight: 100,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
noItemsText: {
|
|
color: colors.text,
|
|
textAlign: 'center',
|
|
marginBottom: 10,
|
|
},
|
|
});
|
|
|
|
const renderContent = () => {
|
|
if (loading && !scheduleData) {
|
|
return;
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<ErrorDisplay message={errorObject?.message} onRefresh={refresh} />
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ErrorBoundary>
|
|
<View style={styles.container}>
|
|
<ScheduleBuilder hours={scheduleData.hours} days={scheduleData.days} type={scheduleData.type} />
|
|
<View style={styles.sideContainer}>
|
|
<View style={styles.sideSectionContainer}>
|
|
<ThemeText style={styles.boxHeader}>Prüfungen</ThemeText>
|
|
{tests.length > 0 ? (
|
|
tests.slice(0, 5).map((test, index) => (
|
|
<View key={index} style={styles.box}>
|
|
<ThemeText numberOfLines={1}>{format(test.date, 'dd.MM.yyyy')}</ThemeText>
|
|
<ThemeText numberOfLines={1}>{`${test.subject} ${test.type}`}</ThemeText>
|
|
</View>
|
|
))
|
|
) : (
|
|
<ThemeText style={styles.noItemsText}>Keine Prüfungen vorhanden</ThemeText>
|
|
)}
|
|
</View>
|
|
<View style={styles.sideSectionContainer}>
|
|
<ThemeText style={styles.boxHeader}>Termine</ThemeText>
|
|
{appointments.length > 0 ? (
|
|
appointments.slice(0, 5).map((appointment, index) => (
|
|
<View key={index} style={styles.box}>
|
|
<ThemeText numberOfLines={2}>{appointment.description}</ThemeText>
|
|
</View>
|
|
))
|
|
) : (
|
|
<ThemeText style={styles.noItemsText}>Keine Termine vorhanden</ThemeText>
|
|
)}
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</ErrorBoundary>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<ScrollView
|
|
// @ts-expect-error - Für Web, TS kennt userSelect nicht
|
|
style={{ flex: 1, backgroundColor: colors.backPrimary, userSelect: 'none' }}
|
|
refreshControl={<RefreshControl refreshing={loading} onRefresh={refresh} colors={[colors.primary]} />}>
|
|
{renderContent()}
|
|
</ScrollView>
|
|
);
|
|
};
|
|
|
|
export default Dashboard;
|
|
|
|
function adjustedDate() {
|
|
let date = new Date();
|
|
|
|
// Check if the current time is past 17:30
|
|
if (date.getHours() > 17 || (date.getHours() === 17 && date.getMinutes() > 30)) {
|
|
date = addDays(date, 1);
|
|
}
|
|
|
|
// Check if the new day is Saturday (6) or Sunday (0)
|
|
let day = date.getDay();
|
|
if (day === 6) {
|
|
date = addDays(date, 2); // Move to Monday
|
|
} else if (day === 0) {
|
|
date = addDays(date, 1); // Move to Monday
|
|
}
|
|
|
|
return new Date(format(date, 'yyyy-MM-dd'));
|
|
}
|