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

225 lines
9.4 KiB
TypeScript

import React, { useCallback, useState } from 'react';
import { FlatList, Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import { ThemeButton, ThemeText } from './ThemeTypes';
import { useColors } from './colors';
import { format, getDay } from 'date-fns';
const dayNames = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
const ScheduleBuilder = ({ hours, days, type }) => {
const colors = useColors();
const [modalVisible, setModalVisible] = useState(false);
const [selected, setSelected] = useState(null);
const openModal = useCallback((day, hour) => {
setSelected({ day: day, hour: hour });
setModalVisible(true);
}, []);
const closeModal = useCallback(() => {
setModalVisible(false);
setSelected(null);
}, []);
const styles = StyleSheet.create({
wrapper: {
alignItems: 'baseline',
},
container: {
flexDirection: 'row',
display: 'flex',
alignItems: 'flex-start',
},
leftColumn: {
width: 80,
paddingTop: 38,
borderRightWidth: 1,
borderColor: '#ccc',
},
timeSlot: {
height: 60,
justifyContent: 'center',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: '#ccc',
},
scheduleContent: {},
dayColumn: {
width: 150,
borderRightWidth: 1,
borderColor: '#ccc',
},
dayHeader: {
height: 38,
},
dayTitle: {
fontWeight: 'bold',
textAlign: 'center',
},
dayDate: {
textAlign: 'center',
},
eventSlot: {
height: 60,
justifyContent: 'center',
borderBottomWidth: 1,
borderColor: '#ccc',
paddingHorizontal: 10,
},
modalOverlay: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.5)',
},
modalContent: {
backgroundColor: colors.backPrimary,
padding: 20,
borderRadius: 10,
alignItems: 'center',
width: '80%',
maxWidth: 500,
},
modalTitle: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 20,
},
closeButton: {
marginTop: 20,
width: '100%',
},
lessonContainer: {
marginBottom: 10,
borderWidth: 2,
borderRadius: 5,
padding: 10,
width: '100%',
},
lessonDetailsContainer: {
flexDirection: 'row',
},
lessonTime: {
fontWeight: 'bold',
paddingRight: 6,
marginRight: 6,
justifyContent: 'center',
alignItems: 'center',
borderColor: '#aaa',
borderRightWidth: 1,
},
lessonDetails: {
flex: 1,
justifyContent: 'center',
},
});
return (
<View style={styles.wrapper}>
<View style={styles.container}>
<View style={styles.leftColumn}>
<FlatList
scrollEnabled={false}
data={hours}
keyExtractor={(item) => item.index}
renderItem={({ item }) => (
<View style={styles.timeSlot}>
<ThemeText>{item.start}</ThemeText>
<ThemeText>{item.end}</ThemeText>
</View>
)}
/>
</View>
{days.map((dayData) => (
<View key={dayData.id} style={styles.scheduleContent}>
<View style={[styles.dayColumn]}>
<View style={[styles.dayHeader]}>
<ThemeText style={styles.dayTitle}>{dayNames[getDay(dayData.date)]}</ThemeText>
<ThemeText style={styles.dayDate}>{format(dayData.date, 'dd.MM.yyyy')}</ThemeText>
</View>
{hours.map((time) => {
let lesson = dayData.lessons.find(
(e) => e.from <= time.index && e.until >= time.index && e.standin
);
if (!lesson) {
lesson = dayData.lessons.find(
(e) => e.from <= time.index && e.until >= time.index
);
}
return (
<TouchableOpacity
style={[
styles.eventSlot,
{ backgroundColor: lesson?.standin ? colors.accent : colors.backPrimary }
]}
key={time.index}
onPress={() => openModal(dayData.id, time.index)}
>
<ThemeText numberOfLines={3}>
{lesson ? `${lesson.subject}\n${type != 'class' ? lesson.class + (lesson.group != 0 ? '-' + lesson.group : '') : ''}${type != 'room' ? ' ' + lesson.room : ''}${type != 'teacher' ? ' ' + lesson.teacher : ''}${lesson.message ? '\n' + lesson.message : ''}` : ''}
</ThemeText>
</TouchableOpacity>
);
})}
</View>
</View>
))}
</View>
{modalVisible && selected.hour !== null && (
<Modal
transparent={true}
visible={modalVisible}
onRequestClose={closeModal}
>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<ThemeText style={styles.modalTitle}>
Stunde {selected.hour}: {hours[selected.hour-1].start} - {hours[selected.hour-1].end}
</ThemeText>
{days.find((day) => day.id === selected.day).lessons
.filter((lesson) => lesson.from <= selected.hour && lesson.until >= selected.hour)
.map((lesson, index) => (
<View key={index} style={[styles.lessonContainer, { borderColor: lesson?.standin ? colors.accent : '#ccc' }]}>
{lesson.standin && (
<ThemeText style={{ marginBottom: 6 }}>Vertretung</ThemeText>
)}
<View style={styles.lessonDetailsContainer}>
<View style={styles.lessonTime}>
<ThemeText>{lesson.from}</ThemeText>
<ThemeText></ThemeText>
<ThemeText>{lesson.until}</ThemeText>
</View>
<View style={styles.lessonDetails}>
<ThemeText>Fach: {lesson.subject}</ThemeText>
{type !== 'class' && (
<>
<ThemeText>Klasse: {lesson.class}</ThemeText>
<ThemeText>Gruppe: {lesson.group === '0' ? 'Beide' : lesson.group}</ThemeText>
</>
)}
{type !== 'teacher' && (
<ThemeText>Lehrer: {lesson.teacher}</ThemeText>
)}
{type !== 'room' && (
<ThemeText>Raum: {lesson.room}</ThemeText>
)}
{lesson.message && (
<ThemeText>Notiz: {lesson.message}</ThemeText>
)}
</View>
</View>
</View>
))}
<ThemeButton onPress={closeModal} style={styles.closeButton}>
<Text>Schließen</Text>
</ThemeButton>
</View>
</View>
</Modal>
)}
</View>
);
};
export default ScheduleBuilder;