Elevate / routes / app / Classes / classPage.js
classPage.js
Raw
import React, { useState, useEffect, useContext } from "react";
import {
  StyleSheet,
  Text,
  SafeAreaView,
  View,
  TouchableOpacity,
  TextInput as Input,
  Keyboard,
} from "react-native";
import { Portal, Button, useTheme, FAB } from "react-native-paper";
import Modal from "react-native-modal";
import Icon from "react-native-vector-icons/FontAwesome5";

import AsyncStorage from "@react-native-async-storage/async-storage";
import { v4 as uuidv4 } from "uuid";
import "react-native-get-random-values";

import { RouteContext } from "../context/routes/RouteContext";
import NewClass from "./newClass";
import NewTask from "./newTask";
import NewTerm from "./newTerm";

import { ClassContext } from "../context/storage/classes/classContext";
import { TaskContext } from "../context/storage/tasks/taskContext";

const globalStyles = require("../../../constants/globalstyles");

export default function ClassPage(props) {
  const { contextClasses, dispatch } = useContext(ClassContext);
  const { contextTasks, dispatch: taskDispatch } = useContext(TaskContext);
  const { route } = useContext(RouteContext);
  const { colors } = useTheme();

  const [className, setClassName] = useState("");
  const [classNum, setClassNum] = useState("");
  const [roomNum, setRoomNum] = useState("");
  const [college, setCollege] = useState("");
  const [addDatesArr, setAddDatesArr] = useState([]);
  const resetClassState = () => {
    setClassName("");
    setClassNum("");
    setRoomNum("");
    setCollege("");
    setAddDatesArr([]);
    setClassInfoId("");

    setClassFocusVis(false);
    setClassFocusInfoVis(false);
    setClassFocusDeleteWarning(false);
  };

  const [selectedDay, setSelectedDay] = useState();
  const [addDate, setAddDate] = useState(new Date());
  const [addTimeStart, setAddTimeStart] = useState(new Date());
  const [addTimeEnd, setAddTimeEnd] = useState(new Date());
  const [addDateVisible, setAddDateVisible] = useState(false);
  const setDate = (e, date) => {
    if (date !== undefined) {
      setAddDate(date);
    }
  };
  const setStartTime = (e, time) => {
    if (time !== undefined) {
      setAddTimeStart(time);
    }
  };
  const setEndTime = (e, time) => {
    if (time !== undefined) {
      setAddTimeEnd(time);
    }
  };
  const addToDateArr = () => {
    var classTime = {
      date: addDate,
      timeStart: addTimeStart,
      timeEnd: addTimeEnd,
    };
    setAddDatesArr((addDatesArr) => [...addDatesArr, classTime]);
    setAddDate(new Date());
    setStartTime(new Date());
    setEndTime(new Date());
    setAddDateVisible(false);
  };

  const formatDay = (day) => {
    switch (day) {
      case 0:
        return "Sunday";
      case 1:
        return "Monday";
      case 2:
        return "Tuesday";
      case 3:
        return "Wednesday";
      case 4:
        return "Thursday";
      case 5:
        return "Friday";
      case 6:
        return "Saturday";
    }
  };
  const formatTime = (time) => {
    if (time.getHours() == 0 || time.getHours() < 12) {
      return time.getHours() + ":" + time.getMinutes() + "AM";
    } else {
      return time.getHours() - 12 + ":" + time.getMinutes() + "PM";
    }
  };

  const [classFocusVis, setClassFocusVis] = useState(false);
  const [classInfoId, setClassInfoId] = useState("");

  const [classFocusInfoVis, setClassFocusInfoVis] = useState(false);
  const [classFocusTasksVis, setClassFocusTasksVis] = useState(false);
  const [classFocusNotesVis, setClassFocusNotesVis] = useState(false);

  const [classFocusDeleteWarning, setClassFocusDeleteWarning] = useState(false);

  const getClassData = (id) => {
    Object.keys(contextClasses).forEach((key) => {
      if (contextClasses[key]["id"] === id) {
        console.log("class with id", contextClasses[key]["id"], "opened!");
        setClassName(contextClasses[key]["className"]);
        setClassNum(contextClasses[key]["classNum"]);
        setRoomNum(contextClasses[key]["roomNum"]);
        setCollege(contextClasses[key]["college"]);
        setClassInfoId(id);
        if (contextClasses[key]["classTimes"]) {
          setAddDatesArr(contextClasses[key]["classTimes"]);
        }
        setClassFocusVis(true);
      }
    });
  };

  const closeClassInfoModal = () => {
    resetClassState();

    setFabVisible(true);
  };

  const deleteClass = () => {
    dispatch({ type: "REMOVE_CLASS", id: classInfoId });
    console.log("Deleted class with ID:", classInfoId);

    resetClassState();
    setClassFocusDeleteWarning(false);
    closeClassInfoModal();
    setFabVisible(true);
  };

  const editClassInfo = async () => {
    try {
      const existingClasses = await AsyncStorage.getItem("classes");
      let classes = JSON.parse(existingClasses);
      for (const property in classes) {
        if (classes[property]["id"] === classInfoId) {
          console.log(classes[property]["id"]);
          classes[property]["className"] = className;
          classes[property]["classNum"] = classNum;
          classes[property]["roomNum"] = roomNum;
          classes[property]["college"] = college;
        }
      }
      await AsyncStorage.setItem("classes", JSON.stringify(classes)).then(
        () => {
          resetClassState();
          setClassFocusVis(false);
          setFabVisible(true);
        }
      );
    } catch (e) {
      console.log(e);
    }
  };

  const [fabOpened, setFabOpened] = useState(false);
  const [fabVisible, setFabVisible] = useState(true);

  const onFabChange = () => {
    if (!fabOpened) {
      console.log("opening fab!");
      if (taskModalVis == true) {
        setTaskModalVis(false);
      } else if (classModalVis == true) {
        setClassModalVis(false);
      } else if (termModalVis == true) {
        setTermModalVis(false);
      }
    } else {
      console.log("closing fab!");
    }
  };

  //Show class FAB only on class route
  useEffect(() => {
    if (route != "classes") {
      setFabVisible(false);
    } else {
      setFabVisible(true);
    }
  }, [route]);

  const [taskModalVis, setTaskModalVis] = useState(false);
  const [classModalVis, setClassModalVis] = useState(false);
  const [termModalVis, setTermModalVis] = useState(false);

  return (
    <>
      <SafeAreaView style={globalStyles.background}>
        <View style={globalStyles.container}>
          {contextClasses.length < 1 ? (
            <View
              style={{
                display: "flex",
                justifyContent: "center",
                height: "100%",
                alignItems: "center",
                marginBottom: 30,
              }}
            >
              <Text
                style={{
                  fontWeight: "bold",
                  color: colors.dark,
                  textAlign: "center",
                  fontSize: 24,
                  marginBottom: 20,
                }}
              >
                You currently do not have any classes added.
              </Text>
              <Text
                style={{
                  fontWeight: "bold",
                  color: colors.dark,
                  textAlign: "center",
                  marginBottom: 50,
                }}
              >
                Click the plus button on the bottom to add a new class!
              </Text>
            </View>
          ) : (
            Object.keys(contextClasses).map((key) => (
              <TouchableOpacity
                style={styles.panel}
                onPress={() => getClassData(contextClasses[key]["id"])}
                key={contextClasses[key]["id"]}
              >
                <Text style={{ fontSize: 18 }}>
                  {contextClasses[key]["className"]}
                </Text>
              </TouchableOpacity>
            ))
          )}
        </View>
      </SafeAreaView>

      <NewTask shown={taskModalVis} />
      <NewClass shown={classModalVis} />
      <NewTerm shown={termModalVis} />

      <Modal
        isVisible={classFocusVis}
        avoidKeyboard={true}
        hasBackdrop={true}
        backdropColor="black"
        style={{
          margin: 0,
        }}
      >
        <View
          style={{
            flex: 1,
            justifyContent: "center",
            marginHorizontal: 25,
          }}
        >
          <View
            style={{
              justifyContent: "center",
              flexDirection: "row",
              paddingHorizontal: 16,
              paddingVertical: 12,
              alignItems: "baseline",
              borderColor: colors.secondaryDarker,
              borderBottomWidth: 1,
              backgroundColor: colors.primary,
              borderTopLeftRadius: 20,
              borderTopRightRadius: 20,
            }}
          >
            {!classFocusDeleteWarning &&
            !classFocusInfoVis &&
            !classFocusTasksVis &&
            !classFocusNotesVis ? (
              <TouchableOpacity
                onPress={() => {
                  Keyboard.dismiss();
                  closeClassInfoModal();
                }}
                style={{ marginRight: "auto" }}
              >
                <Text
                  style={{
                    width: 50,
                    fontSize: 16,
                    color: colors.light,
                    fontWeight: "500",
                  }}
                >
                  Close
                </Text>
              </TouchableOpacity>
            ) : (
              <>
                <TouchableOpacity
                  onPress={() => {
                    Keyboard.dismiss();
                    classFocusInfoVis
                      ? setClassFocusInfoVis(false)
                      : classFocusNotesVis
                      ? setClassFocusNotesVis(false)
                      : classFocusTasksVis
                      ? setClassFocusTasksVis(false)
                      : setClassFocusDeleteWarning(false);
                  }}
                  style={{ marginRight: "auto" }}
                >
                  <Text
                    style={{
                      width: 50,
                      fontSize: 16,
                      color: colors.light,
                      fontWeight: "500",
                    }}
                  >
                    Back
                  </Text>
                </TouchableOpacity>
              </>
            )}
            <View style={{ marginRight: "auto" }}>
              <Text
                style={{
                  color: colors.light,
                  fontSize: 20,
                  fontWeight: "600",

                  position: "relative",
                  margin: "auto",
                  left: -25,
                }}
              >
                {className}
              </Text>
            </View>
          </View>

          <View
            style={{
              backgroundColor: "#fff",
              paddingHorizontal: 16,
              paddingVertical: 12,
              paddingBottom: 16,
              display: "flex",
              borderBottomRightRadius: 20,
              borderBottomLeftRadius: 20,
            }}
          >
            {!classFocusDeleteWarning &&
            !classFocusInfoVis &&
            !classFocusTasksVis &&
            !classFocusNotesVis ? (
              <View>
                <TouchableOpacity
                  style={{
                    display: "flex",
                    flexDirection: "row",
                    justifyContent: "center",
                    backgroundColor: colors.secondary,
                    padding: 12,
                    borderRadius: 10,
                    marginBottom: 10,
                  }}
                  onPress={() => {
                    setClassFocusInfoVis(true);
                  }}
                >
                  <Text style={{ fontWeight: "500" }}>CLASS INFO</Text>
                </TouchableOpacity>

                <TouchableOpacity
                  style={{
                    display: "flex",
                    flexDirection: "row",
                    justifyContent: "center",
                    backgroundColor: colors.secondary,
                    padding: 12,
                    borderRadius: 10,
                    marginBottom: 10,
                  }}
                  onPress={() => {
                    setClassFocusTasksVis(true);
                  }}
                >
                  <Text style={{ fontWeight: "500" }}>TASKS</Text>
                </TouchableOpacity>

                <TouchableOpacity
                  style={{
                    display: "flex",
                    flexDirection: "row",
                    justifyContent: "center",
                    backgroundColor: colors.secondary,
                    padding: 12,
                    borderRadius: 10,
                    marginBottom: 10,
                  }}
                  onPress={() => {
                    setClassFocusNotesVis(true);
                  }}
                >
                  <Text style={{ fontWeight: "500" }}>NOTES</Text>
                </TouchableOpacity>

                <Button
                  icon="minus-circle"
                  mode="contained"
                  onPress={() => {
                    setClassFocusDeleteWarning(true);
                  }}
                  color="#e35053"
                >
                  <Text>Delete Class</Text>
                </Button>
              </View>
            ) : (
              <>
                {classFocusInfoVis && (
                  <>
                    <View
                      style={{
                        borderBottomWidth: 1.5,
                        borderColor: colors.primary,
                        paddingBottom: 4,
                      }}
                    >
                      <Text
                        style={{
                          fontSize: 18,
                          fontWeight: "600",
                          letterSpacing: 1,
                        }}
                      >
                        INFO
                      </Text>
                    </View>
                    <View
                      style={{
                        display: "flex",
                        flexDirection: "column",
                        marginTop: 8,
                      }}
                    >
                      <View
                        style={{
                          display: "flex",
                          marginBottom: 12,
                          padding: 6,
                          borderRadius: 8,
                          backgroundColor: colors.light,
                        }}
                      >
                        <Text
                          style={{
                            fontWeight: "bold",
                            fontSize: 16,
                            marginBottom: 2,
                            color: colors.primary,
                          }}
                        >
                          Class Number
                        </Text>
                        <Input
                          value={classNum}
                          onChangeText={(text) => {
                            setClassNum(text);
                          }}
                          style={{ color: colors.dark }}
                        />
                      </View>
                      <View
                        style={{
                          display: "flex",
                          marginBottom: 12,
                          padding: 6,
                          borderRadius: 8,
                          backgroundColor: colors.light,
                        }}
                      >
                        <Text
                          style={{
                            fontWeight: "bold",
                            fontSize: 16,
                            marginBottom: 2,
                            color: colors.primary,
                          }}
                        >
                          Room Number
                        </Text>
                        <Input
                          value={roomNum}
                          onChangeText={(text) => {
                            setRoomNum(text);
                          }}
                          style={{ color: colors.dark }}
                        />
                      </View>
                      <View
                        style={{
                          display: "flex",
                          marginBottom: 12,
                          padding: 6,
                          borderRadius: 8,
                          backgroundColor: colors.light,
                        }}
                      >
                        <Text
                          style={{
                            fontWeight: "bold",
                            fontSize: 16,
                            marginBottom: 2,
                            color: colors.primary,
                          }}
                        >
                          College
                        </Text>
                        <Input
                          value={college}
                          onChangeText={(text) => {
                            setCollege(text);
                          }}
                          style={{ color: colors.dark }}
                        />
                      </View>
                    </View>
                    <View>
                      <Text
                        style={{
                          color: colors.primary,
                          fontWeight: "bold",
                          marginBottom: 2,
                          marginLeft: 1,
                        }}
                      >
                        Class Times
                      </Text>
                      {addDatesArr.map((datetime) => (
                        <View
                          style={{
                            backgroundColor: colors.light,
                            display: "flex",
                            flexDirection: "row",
                            justifyContent: "space-between",
                            marginBottom: 4,
                            padding: 8,
                            borderRadius: 8,
                          }}
                        >
                          <View
                            style={{
                              display: "flex",
                              flexDirection: "row",
                              justifyContent: "space-between",
                              alignItems: "center",
                            }}
                          >
                            <Text>Every</Text>
                            <Text
                              style={{
                                marginLeft: 4,
                                color: colors.primary,
                                fontWeight: "bold",
                              }}
                            >
                              {formatDay(new Date(datetime["date"]).getDay())}
                            </Text>
                          </View>

                          <View
                            style={{
                              display: "flex",
                              flexDirection: "row",
                              justifyContent: "space-between",
                            }}
                          >
                            <Text
                              style={{
                                color: colors.primary,
                                fontWeight: "bold",
                              }}
                            >
                              {new Date(
                                datetime["timeStart"]
                              ).toLocaleTimeString([], {
                                hour: "2-digit",
                                minute: "2-digit",
                              })}
                            </Text>
                            <Text
                              style={{
                                marginHorizontal: 2,
                                fontWeight: "bold",
                              }}
                            >
                              -
                            </Text>
                            <Text
                              style={{
                                color: colors.primary,
                                fontWeight: "bold",
                              }}
                            >
                              {new Date(datetime["timeEnd"]).toLocaleTimeString(
                                [],
                                {
                                  hour: "2-digit",
                                  minute: "2-digit",
                                }
                              )}
                            </Text>
                          </View>
                        </View>
                      ))}
                    </View>
                  </>
                )}
                {classFocusNotesVis && (
                  <View
                    style={{
                      borderBottomWidth: 1.5,
                      borderColor: colors.primary,
                      paddingBottom: 4,
                    }}
                  >
                    <Text
                      style={{
                        fontSize: 18,
                        fontWeight: "600",
                        letterSpacing: 1,
                      }}
                    >
                      NOTES
                    </Text>
                    <View
                      style={{
                        display: "flex",
                        flexDirection: "row",
                        alignItems: "center",
                        marginLeft: 1,
                      }}
                    >
                      <Text style={{ fontWeight: "300" }}>
                        What's on your mind?
                      </Text>
                    </View>
                  </View>
                )}
                {classFocusTasksVis && (
                  <View>
                    <View
                      style={{
                        borderBottomWidth: 1.5,
                        borderColor: colors.primary,
                        paddingBottom: 4,
                      }}
                    >
                      <Text
                        style={{
                          fontSize: 18,
                          fontWeight: "600",
                          letterSpacing: 1,
                        }}
                      >
                        TASKS
                      </Text>
                      <View
                        style={{
                          display: "flex",
                          flexDirection: "row",
                          alignItems: "center",
                          marginLeft: 1,
                        }}
                      >
                        <Text style={{ fontWeight: "300" }}>
                          Tasks with the tag{" "}
                        </Text>
                        <Text
                          style={{
                            color: colors.primary,
                            fontWeight: "500",
                          }}
                        >
                          {className}
                        </Text>
                        <Text style={{ fontWeight: "300" }}>
                          {" "}
                          will appear here.
                        </Text>
                      </View>
                    </View>
                    <View style={{ marginTop: 12 }}>
                      {Object.keys(contextTasks).map((key) =>
                        Object.keys(
                          contextTasks[key]["taskTags"]["classTags"]
                        ).map((className) => {
                          if (
                            contextTasks[key]["taskTags"]["classTags"][
                              className
                            ] == classInfoId
                          ) {
                            return (
                              <View
                                style={{
                                  backgroundColor: colors.light,
                                  padding: 8,
                                  marginBottom: 8,
                                }}
                              >
                                <Text
                                  style={{
                                    color: colors.dark,
                                    fontWeight: "500",
                                  }}
                                >
                                  {contextTasks[key]["taskName"]}
                                </Text>
                              </View>
                            );
                          }
                        })
                      )}
                    </View>
                  </View>
                )}
                {classFocusDeleteWarning && (
                  <>
                    <View
                      style={{
                        borderBottomWidth: 1.5,
                        borderColor: colors.primary,
                        paddingBottom: 4,
                      }}
                    >
                      <Text
                        style={{
                          fontSize: 18,
                          fontWeight: "600",
                          letterSpacing: 1,
                        }}
                      >
                        DELETING {className}
                      </Text>
                      <View
                        style={{
                          display: "flex",
                          marginLeft: 1,
                        }}
                      >
                        <Text style={{ fontWeight: "300" }}>Are you sure?</Text>
                      </View>
                    </View>
                    <View style={{ marginLeft: 1 }}>
                      <Text style={{ marginTop: 4, color: colors.dark }}>
                        Please note that this action is permenent and cannot be
                        undone.
                      </Text>
                      <Text style={{ marginTop: 4, color: colors.dark }}>
                        Additionally, any tags associated with this class will
                        be removed from tasks.
                      </Text>
                      <Button
                        mode="contained"
                        onPress={() => {
                          setClassFocusDeleteWarning(false);
                        }}
                        color="#fff"
                        labelStyle={{ color: colors.primary }}
                        style={{ marginVertical: 10 }}
                      >
                        Take me back!
                      </Button>
                      <Button
                        mode="contained"
                        onPress={() => {
                          deleteClass();
                        }}
                        color="#fff"
                        labelStyle={{ color: "#e01e37" }}
                      >
                        Confirm and Delete
                      </Button>
                    </View>
                  </>
                )}
              </>
            )}
          </View>
        </View>
      </Modal>

      <Portal>
        <FAB.Group
          open={fabOpened}
          icon={"plus"}
          actions={[
            {
              icon: "pencil",
              label: "New Task",
              onPress: () => {
                setTaskModalVis(true);
                setFabOpened(false);
              },
              style: { marginRight: 8 },
            },
            {
              icon: "google-classroom",
              label: "Add Class",
              onPress: () => {
                setClassModalVis(true);
                setFabOpened(false);
              },
              style: { marginRight: 8 },
            },
            {
              icon: "school",
              label: "New Term",
              onPress: () => {
                setTermModalVis(true);
                setFabOpened(false);
              },
              style: { marginRight: 8 },
            },
          ]}
          onStateChange={onFabChange}
          onPress={() => {
            setFabOpened(!fabOpened);
          }}
          fabStyle={{
            backgroundColor: colors.primary,
            marginBottom: 70,
            marginRight: 25,
          }}
          visible={fabVisible}
        />
      </Portal>
    </>
  );
}

const styles = StyleSheet.create({
  panel: {
    display: "flex",
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    textAlign: "center",
    fontWeight: "normal",
    backgroundColor: "#fff",
    paddingTop: 15,
    paddingBottom: 15,
    marginBottom: 12,
    marginTop: 4,
    marginRight: 4,
    marginLeft: 4,
    borderRadius: 10,
  },
});