133 lines
4.5 KiB
TypeScript
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) }
|
|
} |