diff --git a/package.json b/package.json index b93b903..4c67b29 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,11 @@ "interval-tree-type": "^1.0.1", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-icons": "^4.2.0", "react-router-dom": "^5.2.0", "rrule": "^2.6.8", - "styled-components": "^5.2.1" + "styled-components": "^5.2.1", + "typescript": "^4.3.2" }, "devDependencies": { "@babel/core": "^7.13.10", diff --git a/src/App.styles.tsx b/src/App.styles.tsx index 3501ed1..88a732e 100644 --- a/src/App.styles.tsx +++ b/src/App.styles.tsx @@ -6,7 +6,14 @@ export const AppGlobalStyles = createGlobalStyle` } :root { + /* colors */ --colors-primary: #000; + --primary-purple: #3D2D6B; + --primary-purple-transparent: rgba(73,58,117,0.33); + --primary-blue: #2825A6; + --primary-blue-transparent: rgba(40,37,166,0.33); + + --navbar-height: 70px; } html, diff --git a/src/App.tsx b/src/App.tsx index e572847..d6a9652 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,7 +12,7 @@ const App = () => { - + ) diff --git a/src/Home.tsx b/src/Home.tsx index d7f6dac..9e89f4d 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,19 +1,14 @@ import * as React from "react" import styled from "styled-components" -import LOGO from "./assets/logo.svg" +import { Logo } from "./components/Logo" class Home extends React.Component { render() { return (

- ClassTimes Logo +

Follow your school classes

diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..89ec503 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,16 @@ +import styled from "styled-components" + +export const Button = styled.a` + border-radius: 5px; + color: var(--primary-blue); + cursor: pointer; + margin: 5px; + padding: 12px; + text-decoration: none; + transition: all 0.2s linear; + + &:hover { + box-shadow: inset 0 0 0 2px var(--primary-blue), + 0 1px 4px 0 var(--primary-blue-transparent); + } +` diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index b4b961d..9aad84f 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -1,4 +1,4 @@ -import React from "react" +import * as React from "react" import styled, { createGlobalStyle } from "styled-components" import dayjs, { Dayjs } from "dayjs" import localeData from "dayjs/plugin/localeData" @@ -7,7 +7,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat" import weekday from "dayjs/plugin/weekday" import timezone from "dayjs/plugin/timezone" import utc from "dayjs/plugin/utc" -import { useQuery, gql } from "@apollo/client" +import { useQuery } from "@apollo/client" import IntervalTree from "interval-tree-type" import { RRule, @@ -25,6 +25,15 @@ import { } from "../../types" import { WeekView } from "./WeekView" +// Hooks +import { useSchoolCalendar } from "../../pages/CalendarPage/SchoolCalendarContext" + +// Queries +import LIST_CALENDAR_EVENTS_QUERY from "./graphql/listCalendarEventsQuery.graphql" + +// Helpers +import { mapEdges } from "../../helpers/mapEdges" + dayjs.extend(duration) dayjs.extend(localeData) dayjs.extend(localizedFormat) @@ -33,37 +42,9 @@ dayjs.extend(utc) dayjs.extend(timezone) //dayjs.locale('en') - -const ALL_EVENTS = gql` - query getAllEvents { - listCalendarEvents(filters: null, first: 2) { - edges { - node { - _id - title - isAllDay - durationHours - startDateUtc - endDateUtc - rrule - exceptionsDatesUtc - subject { - name - } - } - cursor - } - pageInfo { - endCursor - hasNextPage - } - } - } -` - interface ICalendar { startAtHour?: number - title?: React.ReactNode + showHoursCount?: number eventTreeCallback: (range: [Dayjs, Dayjs]) => TEventTree } @@ -90,14 +71,11 @@ const generateWeekdays = (selectedDate: Dayjs) => { const generateNow = () => { const now = dayjs() // dayjs.localeData/().weekdays() - - // const week = dayjs.duration({ weeks: 1 }).days() - // const day = - return { now } //JSON.stringify(week) + return { now } } export const Calendar: React.FC = (props) => { - const { eventTreeCallback, title, startAtHour } = props + const { eventTreeCallback, startAtHour } = props const [timezone, setTimezone] = React.useState(() => dayjs.tz.guess()) const { now } = generateNow() const [selectedDate, setSelectedDate] = React.useState(now) @@ -117,7 +95,6 @@ export const Calendar: React.FC = (props) => { return ( - {title && {title}} {selectedDate.format("MMMM YYYY")} @@ -228,15 +205,6 @@ export const eventTreeGenerator: TEventGeneratorTyped = ( value: clonedEventEnd.toISOString(), }, }) - console.log("clonedEvent", { - ruleDate, - clonedEvent, - // sd: clonedEvent.startDateUtc - }) - // clonedEvent.endDateUtc = clonedEvent.startDateUtc.add( - // clonedEvent.durationHours, - // "hours" - // ) tree.insert( clonedEvent._startDateUtc, clonedEvent._endDateUtc, @@ -245,33 +213,7 @@ export const eventTreeGenerator: TEventGeneratorTyped = ( // clonedEvent.startDateUtc = clonedEvent.startDateUtc // clonedEvent.endDateUtc = clonedEvent.endDateUtc.format() } - - console.log({ rule, ruleQuery }) - - // .fromString( - // "DTSTART;TZID=America/Denver:20181101T190000;\n" - // + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=3" - // ) - // const rule = RRule.fromString( - // "DTSTART;TZID=America/Denver:20181101T190000;\n" - // + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=3" - // ) - // // Create a rule: - // const rule = new RRule({ - // freq: RRule.WEEKLY, - // interval: 5, - // byweekday: [RRule.MO, RRule.FR], - // dtstart: new Date(Date.UTC(2012, 1, 1, 10, 30)), - // until: new Date(Date.UTC(2012, 12, 31)) - // }) } - // start.valueOf() - // console.log("Adding event to tree", { - // start, - // end, - // startValueOf: start.valueOf(), - // endValueOf: end.valueOf() - // }) } return { @@ -284,21 +226,15 @@ export const eventTreeGenerator: TEventGeneratorTyped = ( } export const CalendarWithData = () => { - // TODO: Handle unauthorized? - const { loading, error, data } = useQuery(ALL_EVENTS) - - const calendarEventEdges = data?.listCalendarEvents?.edges - - const title = calendarEventEdges?.[0]?.node?.subject?.name // Placeholder! - const events = calendarEventEdges?.map((edge) => edge.node) + const { calendarEvents } = useSchoolCalendar() const eventTreeCallback = React.useCallback( (range: [Dayjs, Dayjs]) => { - const result = eventTreeGenerator(events, range) + const result = eventTreeGenerator(calendarEvents, range) console.log("save eventTree", result) return result }, - [data, events] + [calendarEvents] ) // if (eventTree) { @@ -315,7 +251,7 @@ export const CalendarWithData = () => { {/*
         loading: {loading ? "loading..." : "loaded"} 
@@ -327,14 +263,13 @@ export const CalendarWithData = () => { } const CalendarWrapper = styled.div` - border: 1px solid black; + height: 100%; ` const Pre = styled.pre` text-align: left; ` -const CalendarTitle = styled.h2`` const CalendarSubtitle = styled.div`` const CalendarTimezone = styled.div`` diff --git a/src/components/Calendar/WeekView.tsx b/src/components/Calendar/WeekView.tsx index b833346..d014c4b 100644 --- a/src/components/Calendar/WeekView.tsx +++ b/src/components/Calendar/WeekView.tsx @@ -258,7 +258,6 @@ const WeekViewBody: React.FC = (props) => { const colCount = group.length return Array.from(col).map((ev, eventIndex) => { const { data: event, startDate } = ev - let topPosition = startDate.hour() + startDate.minute() / 60 topPosition *= 100 @@ -267,6 +266,7 @@ const WeekViewBody: React.FC = (props) => { const duration = (event.durationHours * 100) / 24 const isRecurrent = !!event.rrule + const toggled = event.toggled // console.log("[WeekViewEventItem]", { // event, // startDate, @@ -278,6 +278,7 @@ const WeekViewBody: React.FC = (props) => { return ( ` - display: flex; + display: ${(props) => (props.toggled ? "flex" : "none")}; line-height: 1; position: absolute; top: ${(p) => (p.topPosition ? `${p.topPosition}%` : 0)}; diff --git a/src/components/Calendar/graphql/listCalendarEventsQuery.graphql b/src/components/Calendar/graphql/listCalendarEventsQuery.graphql new file mode 100644 index 0000000..d8d7fa0 --- /dev/null +++ b/src/components/Calendar/graphql/listCalendarEventsQuery.graphql @@ -0,0 +1,34 @@ +query listCalendarEventsQuery( + $filters: ListCalendarEventsInput + $first: Float + $after: String + $before: String +) { + listCalendarEvents( + filters: $filters + first: $first + after: $after + before: $before + ) { + edges { + node { + _id + title + isAllDay + durationHours + startDateUtc + endDateUtc + rrule + exceptionsDatesUtc + subject { + name + } + } + cursor + } + pageInfo { + endCursor + hasNextPage + } + } +} diff --git a/src/components/Calendar/graphql/listSubjectsQuery.graphql b/src/components/Calendar/graphql/listSubjectsQuery.graphql new file mode 100644 index 0000000..64ae0c6 --- /dev/null +++ b/src/components/Calendar/graphql/listSubjectsQuery.graphql @@ -0,0 +1,25 @@ +query listSubjectsQuery( + $filters: ListSubjectInput + $first: Float + $after: String + $before: String +) { + listSubjects( + filters: $filters + first: $first + after: $after + before: $before + ) { + edges { + node { + _id + name + } + cursor + } + pageInfo { + endCursor + hasNextPage + } + } +} diff --git a/src/components/CalendarSidebar.tsx b/src/components/CalendarSidebar.tsx new file mode 100644 index 0000000..37a80b4 --- /dev/null +++ b/src/components/CalendarSidebar.tsx @@ -0,0 +1,69 @@ +import * as React from "react" +import styled from "styled-components" +// import { Link } from "react-router" + +// Hooks +import { useSchoolCalendar } from "../pages/CalendarPage/SchoolCalendarContext" + +// Components +import { CalendarTitle } from "./CalendarTitle" +import { Logo } from "./Logo" +import { VerticalAccordion } from "./VerticalAccordion" +import { ItemToggle } from "./ItemToggle" + +// Types +import { ICareer } from "../types/Career" +import { ISubject } from "../types/Subject" + +// Helpers +import { deepClone } from "../helpers/deepClone" +import { mapEdges } from "../helpers/mapEdges" + +export const CalendarSidebar: React.FC = () => { + const { careers, school, setSchool } = useSchoolCalendar() + + const toggleSubject = (careerIndex: number, subjectIndex: number) => { + const updatedSchool = deepClone(school) + const updatedCareerEdges = updatedSchool?.careersConnection?.edges + const updatedSubjectEdges = + updatedCareerEdges[careerIndex]?.node?.subjectsConnection?.edges + const updatedSubject = updatedSubjectEdges[subjectIndex]?.node + updatedSubject.toggled = !updatedSubject?.toggled + + setSchool(updatedSchool) + } + + return ( + + + + {careers?.map((career, cIndex) => { + const { name, subjectsConnection }: ICareer = career + const subjects: ISubject[] = mapEdges(subjectsConnection?.edges) + + return ( + + {subjects?.map((subject, sIndex) => ( + { + toggleSubject(cIndex, sIndex) + }} + /> + ))} + + ) + })} + + ) +} + +// Styled components + +const SidebarWrapper = styled.div` + height: 100vh; + background-color: #fff; + grid-row: span 2; + padding: 25px 10px; +` diff --git a/src/components/CalendarTitle.tsx b/src/components/CalendarTitle.tsx new file mode 100644 index 0000000..6e4c8d8 --- /dev/null +++ b/src/components/CalendarTitle.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import styled from "styled-components" + +interface ICalendarTitleProps { + title: string +} + +export const CalendarTitle: React.FC = (props) => { + const { title } = props + + return ( + + +

{title}

+
+ ) +} + +// Styled components + +const CalendarTitleWrapper = styled.div` + align-items: center; + display: flex; + margin-bottom: 50px; + margin-top: 50px; +` + +const AvatarImage = styled.div` + background-color: #ccc; + border-radius: 50%; + display: inline-block; + flex-basis: 70px; + flex-shrink: 0; + height: 70px; + margin-right: 15px; +` diff --git a/src/components/ItemToggle.tsx b/src/components/ItemToggle.tsx new file mode 100644 index 0000000..b266017 --- /dev/null +++ b/src/components/ItemToggle.tsx @@ -0,0 +1,76 @@ +import * as React from "react" +import styled from "styled-components" + +interface IItemToggleProps { + text: string + toggled: boolean + setToggled: () => void +} + +export const ItemToggle: React.FC = (props) => { + const { text, toggled, setToggled } = props + + return ( + { + setToggled() + }} + > + + {text} + + ) +} + +// Local components + +interface ICheckboxProps { + toggled: boolean +} + +const Checkbox: React.FC = (props) => { + const { toggled } = props + return ( + + {toggled ? : null} + + ) +} + +// Styled Components + +const ToggleWrapper = styled.div` + align-items: center; + cursor: pointer; + display: flex; + justify-content: space-between; +` + +const Text = styled.p` + text-align: right; +` + +interface ICheckboxWrapperProps { + toggled: boolean +} + +const CheckboxWrapper = styled.div` + align-items: center; + background-color: #CCC; + /* background-color: ${(props) => (props.toggled ? "#222" : "#CCC")}; */ + border-radius: 5px; + box-shadow: ${(props) => + props.toggled ? "inset 0 0 0 2px #222" : undefined}; + display: flex; + flex-basis: 20px; + flex-shrink: 0; + justify-content: center; + height: 20px; +` + +const CheckboxMarker = styled.div` + background-color: #222; + border-radius: 2px; + height: 12px; + width: 12px; +` diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx new file mode 100644 index 0000000..1dee7f9 --- /dev/null +++ b/src/components/Logo.tsx @@ -0,0 +1,13 @@ +import * as React from "react" +import LOGO from "../assets/logo.svg" + +interface ILogoProps { + height?: number +} + +export const Logo: React.FC = (props) => { + const { height } = props + return ( + ClassTimes Logo + ) +} diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx new file mode 100644 index 0000000..049f3ad --- /dev/null +++ b/src/components/Navbar.tsx @@ -0,0 +1,22 @@ +import * as React from "react" +import styled from "styled-components" + +// Components +import { Button } from "../components/Button" + +export const Navbar: React.FC = () => { + return ( + + + + + ) +} + +const NavbarWrapper = styled.nav` + background-color: #fff; + display: flex; + flex-direction: row-reverse; + align-items: center; + padding-right: 20px; +` diff --git a/src/components/VerticalAccordion.tsx b/src/components/VerticalAccordion.tsx new file mode 100644 index 0000000..5dd0e5a --- /dev/null +++ b/src/components/VerticalAccordion.tsx @@ -0,0 +1,70 @@ +import * as React from "react" +import styled from "styled-components" +import { FiChevronDown } from "react-icons/fi" + +interface IVerticalAccordionProps { + title: string + children: JSX.Element[] | JSX.Element +} + +export const VerticalAccordion: React.FC = (props) => { + const { title, children } = props + + const [visible, setVisible] = React.useState(false) + + const toggleAccordion = () => { + setVisible(!visible) + } + + return ( + + +

{title}

+ + + +
+ {children} +
+ ) +} + +// Styled components + +interface IVisibilityProps { + visible: boolean +} + +const AccordionWrapper = styled.div` + border-radius: 5px; + padding: 5px 15px; + transition: all 0.15s linear; + &:hover { + box-shadow: 0 1px 4px 0 #666; + } +` + +const Arrow = styled.div` + display: flex; + justify-content: center; + align-items: center; + transform: rotate(${(props) => (props.visible ? "180deg" : "0deg")}); + transform-origin: center center; +` + +const Dropdown = styled.div` + display: ${(props) => (props.visible ? undefined : "none")}; + /* user-select: none; */ +` + +const DropdownToggle = styled.div` + align-items: center; + cursor: pointer; + display: flex; + justify-content: space-between; + width: 100%; + p { + margin-bottom: 10px; + margin-top: 10px; + } +` diff --git a/src/helpers/addStateVariablesToSchool.ts b/src/helpers/addStateVariablesToSchool.ts new file mode 100644 index 0000000..1be6172 --- /dev/null +++ b/src/helpers/addStateVariablesToSchool.ts @@ -0,0 +1,21 @@ +// Helpers +import { deepClone } from "./deepClone" + +// Types +import { ISchool } from "../types/School" + +export const addStateVariablesToSchool = (schoolRawData: ISchool): ISchool => { + const updatedSchool = deepClone(schoolRawData) + + if (updatedSchool?.careersConnection) { + for (let careerEdge of updatedSchool.careersConnection?.edges) { + if (careerEdge.node?.subjectsConnection) { + for (let subjectEdge of careerEdge.node.subjectsConnection.edges) { + subjectEdge.node.toggled = true + } + } + } + } + + return updatedSchool +} diff --git a/src/helpers/deepClone.ts b/src/helpers/deepClone.ts new file mode 100644 index 0000000..4b33d8b --- /dev/null +++ b/src/helpers/deepClone.ts @@ -0,0 +1,4 @@ +export const deepClone = (object: T): T => { + if (!object) return object + return JSON.parse(JSON.stringify(object)) +} diff --git a/src/helpers/mapEdges.tsx b/src/helpers/mapEdges.tsx new file mode 100644 index 0000000..df559d4 --- /dev/null +++ b/src/helpers/mapEdges.tsx @@ -0,0 +1,5 @@ +import { IEdge } from "../types/Connection" + +export const mapEdges = (edges: IEdge[]): T[] => { + return edges?.map((edge) => edge?.node) +} diff --git a/src/layouts/CalendarLayout.tsx b/src/layouts/CalendarLayout.tsx new file mode 100644 index 0000000..e1713b0 --- /dev/null +++ b/src/layouts/CalendarLayout.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import styled from "styled-components" + +// Components +import { Navbar } from "../components/Navbar" +import { CalendarSidebar } from "../components/CalendarSidebar" + +interface ICalendarLayoutProps { + children: JSX.Element[] | JSX.Element +} + +export const CalendarLayout: React.FC = (props) => { + const { children } = props + + return ( + + + + {children} + + ) +} + +const LayoutWrapper = styled.div` + display: grid; + grid-template-columns: 250px auto; + grid-template-rows: var(--navbar-height) auto; +` diff --git a/src/pages/CalendarPage/CalendarPage.tsx b/src/pages/CalendarPage/CalendarPage.tsx index b761ad9..0b05855 100644 --- a/src/pages/CalendarPage/CalendarPage.tsx +++ b/src/pages/CalendarPage/CalendarPage.tsx @@ -1,9 +1,65 @@ +import * as React from "react" import { CalendarWithData } from "../../components/Calendar" +import { useParams } from "react-router" +import { useQuery } from "@apollo/client" + +// Helpers +import { addStateVariablesToSchool } from "../../helpers/addStateVariablesToSchool" +import { mapEdges } from "../../helpers/mapEdges" + +// Layout +import { CalendarLayout } from "../../layouts/CalendarLayout" + +// Context +import { SchoolCalendarContext } from "./SchoolCalendarContext" + +// Queries +import GET_SCHOOL_QUERY from "./graphql/getSchoolQuery.graphql" + +// Types +import { ICalendarEvent } from "../../types/CalendarEvent" +import { ICareer } from "../../types/Career" +import { ISubject } from "../../types/Subject" export function Page() { + const { schoolShortName } = useParams() + const { loading, error, data } = useQuery(GET_SCHOOL_QUERY, { + variables: { shortName: schoolShortName }, + }) + + // TODO: Don't know if it's a good practice to have the entire state in one giant object + + /* Preprocessing step to add state variables to school object */ + const schoolRawData = data?.school + const schoolInitialValue = addStateVariablesToSchool(schoolRawData) + + /* Set school as state for Context */ + const [school, setSchool] = React.useState(schoolInitialValue) + + /* Set related variables for faster access */ + const careers: ICareer[] = mapEdges(school?.careersConnection?.edges) || [] + let subjects: ISubject[] = [] + for (let career of careers) { + subjects = subjects.concat(mapEdges(career?.subjectsConnection?.edges)) + } + let calendarEvents: ICalendarEvent[] = [] + for (let subject of subjects) { + const mappedEvents = mapEdges(subject?.calendarEventsConnection?.edges) + for (let event of mappedEvents) { + event.toggled = subject.toggled + } + calendarEvents = calendarEvents.concat(mappedEvents) + } + return (
- + + + + +
) } diff --git a/src/pages/CalendarPage/SchoolCalendarContext.tsx b/src/pages/CalendarPage/SchoolCalendarContext.tsx new file mode 100644 index 0000000..143549b --- /dev/null +++ b/src/pages/CalendarPage/SchoolCalendarContext.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +// Types +import { ICalendarEvent } from "../../types/CalendarEvent" +import { ICareer } from "../../types/Career" +import { ISchool } from "../../types/School" +interface IDefaultValue { + calendarEvents?: ICalendarEvent[] + careers?: ICareer[] + school?: ISchool + setSchool?: React.Dispatch +} + +const defaultValue: IDefaultValue = { + calendarEvents: undefined, + careers: undefined, + school: undefined, + setSchool: undefined, +} + +export const SchoolCalendarContext = React.createContext(defaultValue) +export const useSchoolCalendar = () => { + return React.useContext(SchoolCalendarContext) +} diff --git a/src/pages/CalendarPage/graphql/getSchoolQuery.graphql b/src/pages/CalendarPage/graphql/getSchoolQuery.graphql new file mode 100644 index 0000000..c29e4db --- /dev/null +++ b/src/pages/CalendarPage/graphql/getSchoolQuery.graphql @@ -0,0 +1,32 @@ +query getSchoolQuery($shortName: String!) { + school(shortName: $shortName) { + name + careersConnection { + edges { + node { + name + subjectsConnection { + edges { + node { + name + calendarEventsConnection { + edges { + node { + title + isAllDay + durationHours + startDateUtc + endDateUtc + rrule + exceptionsDatesUtc + } + } + } + } + } + } + } + } + } + } +} diff --git a/src/types/CalendarEvent.ts b/src/types/CalendarEvent.ts new file mode 100644 index 0000000..770ade6 --- /dev/null +++ b/src/types/CalendarEvent.ts @@ -0,0 +1,10 @@ +export interface ICalendarEvent { + title?: string + isAllDay?: boolean + durationHours?: number + startDateUtc?: Date + endDateUtc?: Date + rrule?: string + exceptionsDatesUtc?: any // TODO: Better typing + toggled?: boolean +} diff --git a/src/types/Career.ts b/src/types/Career.ts new file mode 100644 index 0000000..8d9fc02 --- /dev/null +++ b/src/types/Career.ts @@ -0,0 +1,7 @@ +import { IConnection } from "./Connection" +import { ISubject } from "./Subject" + +export interface ICareer { + name?: string + subjectsConnection?: IConnection +} diff --git a/src/types/Connection.ts b/src/types/Connection.ts new file mode 100644 index 0000000..dad4861 --- /dev/null +++ b/src/types/Connection.ts @@ -0,0 +1,15 @@ +export interface IEdge { + node?: NodeType + cursor?: string +} + +interface IPageInfo { + hasNextPage?: boolean + endCursor?: string +} + +export interface IConnection { + edges?: IEdge[] + pageInfo?: IPageInfo + totalCount?: number +} diff --git a/src/types/School.ts b/src/types/School.ts new file mode 100644 index 0000000..2db9d60 --- /dev/null +++ b/src/types/School.ts @@ -0,0 +1,7 @@ +import { IConnection } from "./Connection" +import { ICareer } from "./Career" + +export interface ISchool { + name?: string + careersConnection?: IConnection +} diff --git a/src/types/Subject.ts b/src/types/Subject.ts new file mode 100644 index 0000000..bc74ed0 --- /dev/null +++ b/src/types/Subject.ts @@ -0,0 +1,9 @@ +import { IConnection } from "./Connection" +import { ICalendarEvent } from "./CalendarEvent" + +export interface ISubject { + _id?: string + name?: string + toggled?: boolean + calendarEventsConnection?: IConnection +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e40525a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "commonjs", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react" + }, + "include": ["src"] +} diff --git a/yarn.lock b/yarn.lock index 4f013bd..d51c78d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11702,6 +11702,11 @@ react-hotkeys@2.0.0: dependencies: prop-types "^15.6.1" +react-icons@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.2.0.tgz#6dda80c8a8f338ff96a1851424d63083282630d0" + integrity sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ== + react-inspector@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-5.1.0.tgz#45a325e15f33e595be5356ca2d3ceffb7d6b8c3a" @@ -13768,6 +13773,11 @@ typescript-plugin-styled-components@^1.4.4: resolved "https://registry.yarnpkg.com/typescript-plugin-styled-components/-/typescript-plugin-styled-components-1.4.4.tgz#fff26d516ff213dffe1a5627fe76f23ae3ee6ada" integrity sha512-w5S5lSpzRFM+61KNNpGtlF46DuTJTyzfWM4g6ic9m189ILEoU3sgoTNHNS2MxQhXsGtQZwAlINKG+Dwy0euwUg== +typescript@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" + integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw== + unbox-primitive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f"