import React, { useState, useEffect, useContext } from "react"; import { StyleSheet, Text, View, TouchableOpacity, TextInput as Input, Keyboard, } from "react-native"; import Modal from "react-native-modal"; import { Button, useTheme } from "react-native-paper"; import Icon from "react-native-vector-icons/FontAwesome5"; import DateTimePicker from "@react-native-community/datetimepicker"; import AsyncStorage from "@react-native-async-storage/async-storage"; import "react-native-get-random-values"; import { v4 as uuidv4 } from "uuid"; import { ClassContext } from "../context/storage/classes/classContext"; export default function NewClass(props) { const { colors } = useTheme(); const { dispatch } = useContext(ClassContext); const [classModalVis, setClassModalVis] = useState(props.shown); useEffect(() => { setClassModalVis(props.shown); }, [props.shown]); const [className, setClassName] = useState(""); const [classNameErr, setClassNameErr] = useState(false); const [classNum, setClassNum] = useState(""); const [roomNum, setRoomNum] = useState(""); const [college, setCollege] = useState(""); const [addDatesArr, setAddDatesArr] = useState([]); const addClass = async () => { if (className !== "") { dispatch({ type: "ADD_CLASS", class: { className, classNum, roomNum, college, addDatesArr, }, }); Keyboard.dismiss(); resetNewClass(); } else { setClassNameErr(true); } }; const resetNewClass = () => { setClassModalVis(false); setClassName(""); setClassNum(""); setRoomNum(""); setCollege(""); resetNewSchedule(); }; const [scheduleClicked, setScheduleClicked] = useState(false); const [scheduleModalVis, setScheduleModalVis] = useState(false); const [addTimeStart, setAddTimeStart] = useState(new Date()); const setStartTime = (e, time) => { if (time !== undefined) { setAddTimeStart(time); } }; const [addTimeEnd, setAddTimeEnd] = useState(new Date()); const setEndTime = (e, time) => { if (time !== undefined) { setAddTimeEnd(time); } }; const [scheduleType, setScheduleType] = useState(1); const [addDate, setAddDate] = useState(new Date()); const setDate = (e, date) => { if (date !== undefined) { setAddDate(date); } }; const addSingleDateState = () => { var classTime = { date: addDate, timeStart: addTimeStart, timeEnd: addTimeEnd, id: uuidv4(), }; setAddDatesArr((addDatesArr) => [...addDatesArr, classTime]); setAddDate(new Date()); setStartTime(new Date()); setEndTime(new Date()); console.log("single date added!"); }; const [recurringDays, setRecurringDays] = useState({ sun: false, mon: false, tues: false, wed: false, thurs: false, fri: false, sat: false, }); const addRecurringDatesState = async () => { for (const day in recurringDays) { if (recurringDays[day] == true) { var classTime = { date: getNextDayOfTheWeek(day), timeStart: addTimeStart, timeEnd: addTimeEnd, id: uuidv4(), }; await setAddDatesArr((addDatesArr) => [...addDatesArr, classTime]); } } setRecurringDays({ sun: false, mon: false, tues: false, wed: false, thurs: false, fri: false, sat: false, }); console.log("recurring dates added!"); }; const getNextDayOfTheWeek = ( dayName, excludeToday = false, refDate = new Date() ) => { const dayOfWeek = [ "sun", "mon", "tues", "wed", "thurs", "fri", "sat", ].indexOf(dayName); if (dayOfWeek < 0) return; refDate.setHours(0, 0, 0, 0); refDate.setDate( refDate.getDate() + +!!excludeToday + ((dayOfWeek + 7 - refDate.getDay() - +!!excludeToday) % 7) ); return refDate; }; const resetNewSchedule = () => { setScheduleModalVis(false); setAddDatesArr([]); setAddDate(new Date()); setAddTimeStart(new Date()); setAddTimeEnd(new Date()); setRecurringDays({ sun: false, mon: false, tues: false, wed: false, thurs: false, fri: false, sat: false, }); }; var getDayOfWeek = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ]; return ( <> <Modal isVisible={classModalVis} avoidKeyboard={true} hasBackdrop={true} backdropColor="black" onModalHide={() => { if (scheduleClicked == true) { setScheduleModalVis(true); setScheduleClicked(false); } }} style={{ margin: 0, }} > <View style={{ flex: 1, justifyContent: "flex-end", }} > <View style={{ justifyContent: "space-between", flexDirection: "row", paddingHorizontal: 20, paddingVertical: 18, alignItems: "baseline", borderColor: colors.secondaryDarker, borderBottomWidth: 1, backgroundColor: colors.secondary, borderTopLeftRadius: 25, borderTopRightRadius: 25, }} > <TouchableOpacity onPress={() => { Keyboard.dismiss(); resetNewClass(); }} > <Text style={{ width: 50, fontSize: 16, color: colors.primary, fontWeight: "500", }} > Close </Text> </TouchableOpacity> <Text style={{ color: colors.dark, fontSize: 20, fontWeight: "600" }} > New Class </Text> <TouchableOpacity onPress={() => { addClass(); }} > <Text style={{ width: 50, fontSize: 16, color: colors.primary, fontWeight: "500", textAlign: "right", }} > Add </Text> </TouchableOpacity> </View> <View style={{ padding: 15, backgroundColor: "#fff" }}> {classNameErr && ( <View style={{ display: "flex", flexDirection: "row", alignItems: "baseline", marginLeft: 1, marginBottom: 4, }} > <Icon name="exclamation-circle" size={16} color={colors.red} /> <Text style={{ fontSize: 15, color: colors.red, marginLeft: 4, }} > This field is required. </Text> </View> )} <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", }} > <View style={{ backgroundColor: colors.secondary, width: "64%", padding: 14, paddingRight: 0, borderRadius: 8, borderColor: classNameErr == true ? colors.red : colors.secondaryDarker, borderWidth: 1, display: "flex", flexDirection: "column", }} > <Input placeholder="Class Name" autoFocus={true} value={className} onChangeText={(text) => { setClassName(text); setClassNameErr(false); }} keyboardType="twitter" autoCorrect={false} autoCapitalize="none" style={{ fontSize: 16 }} /> </View> <View style={{ backgroundColor: colors.secondary, width: "34%", padding: 14, paddingRight: 0, borderRadius: 8, borderColor: colors.secondaryDarker, borderWidth: 1, }} > <Input placeholder="Class #" value={classNum} onChangeText={(text) => setClassNum(text)} keyboardType="twitter" autoCorrect={false} autoCapitalize="none" style={{ fontSize: 16 }} /> </View> </View> <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", marginTop: 15, }} > <View style={{ backgroundColor: colors.secondary, width: "49%", padding: 14, paddingRight: 0, borderRadius: 8, borderColor: colors.secondaryDarker, borderWidth: 1, display: "flex", flexDirection: "column", }} > <Input placeholder="Room #" value={roomNum} onChangeText={(text) => setRoomNum(text)} keyboardType="twitter" autoCorrect={false} autoCapitalize="none" style={{ fontSize: 16 }} /> </View> <View style={{ backgroundColor: colors.secondary, width: "49%", padding: 14, paddingRight: 0, borderRadius: 8, borderColor: colors.secondaryDarker, borderWidth: 1, }} > <Input placeholder="College" value={college} onChangeText={(text) => setCollege(text)} keyboardType="twitter" autoCorrect={false} autoCapitalize="none" style={{ fontSize: 16 }} /> </View> </View> {addDatesArr.length > 0 && ( <View style={{ marginTop: 8, }} > <Text style={{ fontWeight: "bold", fontSize: 16, color: colors.primary, marginBottom: 2, }} > Occurences </Text> <View style={{ backgroundColor: colors.secondary, padding: 12, borderRadius: 8, }} > {addDatesArr.map((item, i) => ( <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", marginBottom: 2, }} > <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center", }} > <Text style={{ color: colors.dark, fontSize: 16 }}> Every </Text> <Text style={{ marginLeft: 4, color: colors.primary, fontSize: 16, fontWeight: "bold", }} > {getDayOfWeek[new Date(item.date).getDay()]} </Text> </View> <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", }} > <Text style={{ color: colors.primary, fontSize: 16, fontWeight: "bold", }} > {new Date(item.timeStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", })} </Text> <Text style={{ marginHorizontal: 2, fontWeight: "bold", color: colors.dark, fontSize: 16, }} > - </Text> <Text style={{ color: colors.primary, fontSize: 16, fontWeight: "bold", }} > {new Date(item.timeEnd).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", })} </Text> </View> </View> ))} </View> </View> )} <Button icon="calendar" mode="contained" onPress={() => { Keyboard.dismiss(); setScheduleClicked(true); setClassModalVis(false); }} style={{ marginTop: 14 }} > <Text>Schedule</Text> </Button> </View> </View> </Modal> <Modal isVisible={scheduleModalVis} avoidKeyboard={true} hasBackdrop={true} backdropColor="black" onSwipeComplete={() => resetNewSchedule()} onModalHide={() => { setClassModalVis(true); }} swipeDirection="down" style={{ margin: 0, }} > <View style={{ flex: 1, justifyContent: "flex-end", }} > <View style={{ display: "flex", justifyContent: "space-between", flexDirection: "row", paddingHorizontal: 20, paddingVertical: 18, alignItems: "baseline", borderColor: colors.secondaryDarker, borderBottomWidth: 1, backgroundColor: colors.secondary, borderTopLeftRadius: 25, borderTopRightRadius: 25, }} > <TouchableOpacity onPress={() => { resetNewSchedule(); }} > <Text style={{ width: 60, fontSize: 16, color: colors.primary, fontWeight: "500", }} > Close </Text> </TouchableOpacity> <View style={{ borderTopWidth: 5, borderColor: colors.secondaryAccent, borderRadius: 3, }} > <Text style={{ color: colors.dark, fontSize: 20, fontWeight: "600", paddingTop: 16, }} > Schedule </Text> </View> <TouchableOpacity onPress={() => setScheduleModalVis(false)}> <Text style={{ width: 60, fontSize: 16, color: colors.primary, fontWeight: "500", textAlign: "right", }} > Add </Text> </TouchableOpacity> </View> <View style={{ backgroundColor: "#fff" }}> <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", padding: 15, }} > <TouchableOpacity style={{ width: "49%", padding: 8, backgroundColor: scheduleType == 0 ? colors.primary : colors.secondary, borderRadius: 10, }} onPress={() => { setScheduleType(0); setAddDate(new Date()); }} > <Text style={{ textAlign: "center", fontSize: 16, color: scheduleType == 0 ? "#fff" : colors.dark, }} > Single Date </Text> </TouchableOpacity> <TouchableOpacity style={{ width: "49%", padding: 8, backgroundColor: scheduleType == 1 ? colors.primary : colors.secondary, borderRadius: 10, }} onPress={() => { setScheduleType(1); setAddDate(new Date()); }} > <Text style={{ textAlign: "center", fontSize: 16, color: scheduleType == 1 ? "#fff" : colors.dark, }} > Recurring </Text> </TouchableOpacity> </View> <View style={{ paddingHorizontal: 15 }}> {scheduleType == 0 ? ( <> <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", }} > <View style={{ display: "flex", flexDirection: "column", width: "45%", }} > <Text style={{ fontSize: 18, fontWeight: "300", marginBottom: 2, }} > Date </Text> <DateTimePicker display="default" mode={"date"} is24Hour={false} value={addDate} onChange={setDate} /> </View> <View style={{ display: "flex", flexDirection: "column", width: "27.5%", }} > <Text style={{ fontSize: 18, fontWeight: "300", marginBottom: 2, }} > Start Time </Text> <DateTimePicker display="default" mode={"time"} is24Hour={false} minuteInterval={5} value={addTimeStart} onChange={setStartTime} /> </View> <View style={{ display: "flex", flexDirection: "column", width: "27.5%", }} > <Text style={{ fontSize: 18, fontWeight: "300", marginBottom: 2, }} > End Time </Text> <DateTimePicker display="default" mode={"time"} is24Hour={false} minuteInterval={5} value={addTimeEnd} onChange={setEndTime} /> </View> </View> <Button icon="plus-circle" mode="contained" onPress={addSingleDateState} style={{ marginTop: 15 }} > <Text>CONFIRM</Text> </Button> </> ) : ( <> <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", }} > <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, sun: !recurringDays.sun, }); }} style={{ backgroundColor: recurringDays.sun ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, borderTopLeftRadius: 8, borderBottomLeftRadius: 8, width: "14.2856%", justifyContent: "center", }} > <Text style={{ color: recurringDays.sun ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Sun </Text> </TouchableOpacity> <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, mon: !recurringDays.mon, }); }} style={{ backgroundColor: recurringDays.mon ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, width: "14.2856%", justifyContent: "center", }} > <Text style={{ color: recurringDays.mon ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Mon </Text> </TouchableOpacity> <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, tues: !recurringDays.tues, }); }} style={{ backgroundColor: recurringDays.tues ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, width: "14.2856%", justifyContent: "center", }} > <Text style={{ color: recurringDays.tues ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Tue </Text> </TouchableOpacity> <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, wed: !recurringDays.wed, }); }} style={{ backgroundColor: recurringDays.wed ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, width: "14.2856%", justifyContent: "center", }} > <Text style={{ color: recurringDays.wed ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Wed </Text> </TouchableOpacity> <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, thurs: !recurringDays.thurs, }); }} style={{ backgroundColor: recurringDays.thurs ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, width: "14.2856%", justifyContent: "center", }} > <Text style={{ color: recurringDays.thurs ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Thu </Text> </TouchableOpacity> <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, fri: !recurringDays.fri, }); }} style={{ backgroundColor: recurringDays.fri ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, width: "14.2856%", justifyContent: "center", }} > <Text style={{ color: recurringDays.fri ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Fri </Text> </TouchableOpacity> <TouchableOpacity onPress={() => { setRecurringDays({ ...recurringDays, sat: !recurringDays.sat, }); }} style={{ backgroundColor: recurringDays.sat ? colors.primary : colors.secondary, paddingHorizontal: 5, paddingVertical: 10, borderTopRightRadius: 8, borderBottomRightRadius: 8, width: "14.285%", justifyContent: "center", }} > <Text style={{ color: recurringDays.sat ? "#fff" : colors.dark, fontWeight: "500", fontSize: 16, textAlign: "center", }} > Sat </Text> </TouchableOpacity> </View> <View style={{ marginTop: 15, display: "flex", flexDirection: "row", }} > <View style={{ display: "flex", flexDirection: "column", width: "50%", alignItems: "center", paddingRight: "5%", }} > <Text style={{ fontSize: 18, fontWeight: "300", marginBottom: 2, }} > Start Time </Text> <DateTimePicker display="default" mode={"time"} is24Hour={false} minuteInterval={5} value={addTimeStart} onChange={setStartTime} textColor={colors.primary} style={{ width: 90 }} /> </View> <View style={{ display: "flex", flexDirection: "column", width: "50%", alignItems: "center", paddingLeft: "5%", }} > <Text style={{ fontSize: 18, fontWeight: "300", marginBottom: 2, }} > End Time </Text> <DateTimePicker display="default" mode={"time"} is24Hour={false} minuteInterval={5} value={addTimeEnd} onChange={setEndTime} textColor={colors.primary} style={{ width: 90 }} /> </View> </View> <Button icon="plus-circle" mode="contained" onPress={addRecurringDatesState} style={{ marginTop: 15 }} > <Text>CONFIRM</Text> </Button> </> )} </View> <View style={{ padding: 10, paddingHorizontal: 16, borderTopWidth: 1, borderColor: colors.secondaryDarker, marginBottom: "5%", marginTop: 20, }} > <Text style={{ fontWeight: "bold", fontSize: 16, color: colors.primary, marginBottom: 2, marginLeft: 1, }} > Occurences </Text> {addDatesArr.length > 0 ? ( <View style={{ backgroundColor: colors.secondary, padding: 12, borderRadius: 8, }} > {addDatesArr.map((item, i) => ( <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", marginBottom: 2, }} > <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center", }} > <Text style={{ color: colors.dark, fontSize: 16 }}> Every </Text> <Text style={{ marginLeft: 4, color: colors.primary, fontSize: 16, fontWeight: "bold", }} > {getDayOfWeek[new Date(item.date).getDay()]} </Text> </View> <View style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", }} > <Text style={{ color: colors.primary, fontSize: 16, fontWeight: "bold", }} > {new Date(item.timeStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", })} </Text> <Text style={{ marginLeft: 4, marginRight: 4, fontWeight: "bold", color: colors.dark, fontSize: 16, }} > - </Text> <Text style={{ color: colors.primary, fontSize: 16, fontWeight: "bold", }} > {new Date(item.timeEnd).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", })} </Text> </View> </View> ))} </View> ) : ( <Text style={{ color: colors.dark }}> Added times will appear here after entering dates/times and pressing confirm. </Text> )} </View> </View> </View> </Modal> </> ); }