Files
klatab/screens/Schedule.tsx
2024-09-15 14:36:20 +02:00

133 lines
4.5 KiB
TypeScript

import { Picker } from '@react-native-picker/picker';
import { getISOWeek, addWeeks, subWeeks } from 'date-fns';
import React, { useContext, useEffect, useState } from 'react';
import { Modal, ScrollView, StyleSheet, View, Text } from 'react-native';
import ErrorBoundary from 'react-native-error-boundary';
import { RefreshControl } from 'react-native-web-refresh-control';
import { InterfaceContext } from '../Interface';
import { SettingsContext } from '../SettingsProvider';
import DatePicker from '../common/DatePicker';
import ErrorDisplay from '../common/ErrorDisplay';
import ScheduleBuilder from '../common/ScheduleBuilder';
import { ThemeButton, ThemeText } from '../common/ThemeTypes';
import { useColors } from '../common/colors';
import { AntDesign } from '@expo/vector-icons';
import FilterModal from '../common/FilterModal';
let errorObject;
let categories = { class: 'Klasse', room: 'Raum', teacher: 'Lehrer' };
const Schedule = () => {
const colors = useColors();
const [scheduleData, setScheduleData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const { fetchTimes, fetchScheduleByWeek, refreshInterface, userInformation, baseData } = useContext(InterfaceContext);
const { settings } = useContext(SettingsContext);
const [showFilterModal, setShowFilterModal] = useState(false);
const [date, setDate] = useState(new Date());
const [filter, setFilter] = useState(getDefaultFilter(userInformation));
const fetchData = async () => {
try {
setLoading(true);
if (!userInformation || !baseData) {
refreshInterface()
throw new Error("BaseData or UserInformation is Null");
}
const hours = await fetchTimes();
const year = date.getFullYear();
const week = getISOWeek(date);
if (!filter) throw new Error("Filter is null");
const days = await fetchScheduleByWeek(filter.type, filter.value, filter.group, week, year);
if (!hours || !days) throw new Error("Data returned is Null");
setScheduleData({ hours, days });
setError(false);
} catch (error) {
console.error(error)
errorObject = error;
setError(true);
} finally {
setLoading(false);
}
}
useEffect(() => {
fetchData();
}, [filter, date]);
useEffect(() => {
setFilter(getDefaultFilter(userInformation));
}, [userInformation])
const refresh = () => {
fetchData();
};
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
paddingRight: 10,
gap: 10,
},
picker: {
color: colors.text,
backgroundColor: colors.backPrimary,
},
});
const renderContent = () => {
if (loading && !scheduleData) {
return null;
}
if (error) {
return (
<ErrorDisplay message={errorObject?.message} onRefresh={refresh} />
)
}
return (
<ErrorBoundary>
<ScrollView horizontal>
<ScheduleBuilder hours={scheduleData.hours} days={scheduleData.days} type={filter.type} />
</ScrollView>
</ErrorBoundary>
);
};
return (
<View style={{ flex: 1, backgroundColor: colors.backPrimary }}>
<View style={styles.container}>
<ThemeButton onPress={() => { setDate(new Date) }} ><Text>Heute</Text></ThemeButton>
<ThemeButton onPress={() => { setDate(subWeeks(date, 1)) }} ><AntDesign name="caretleft" size={24} /></ThemeButton>
<DatePicker
date={date}
setDate={setDate}
/>
<ThemeButton onPress={() => { setDate(addWeeks(date, 1)); }} ><AntDesign name="caretright" size={24} /></ThemeButton>
<FilterModal filter={filter} setFilter={setFilter} userInformation={userInformation} baseData={baseData}></FilterModal>
</View >
<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>
</View>
);
};
export default Schedule;
const getDefaultFilter = (userInformation) => {
if (!userInformation) return null
let type = userInformation.usertype == 'pupil' ? 'class' : 'teacher';
let value = userInformation.usertype == 'pupil' ? userInformation.classid : userInformation.id;
return { type: type, value: value, group: String(userInformation.group) }
}