Skip to content

Commit

Permalink
displaying lesson plans
Browse files Browse the repository at this point in the history
  • Loading branch information
kubagp1 committed Feb 13, 2022
1 parent 0e45788 commit 4cfb353
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 18 deletions.
5 changes: 0 additions & 5 deletions mock-api/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,6 @@
},
{
"id": 1,
"name": "1B 1Tinf",
"category": {
"type": "students",
"name": "1"
},
"hours": ["7:10 - 7:55"],
"lessons": {
"monday": [[null]],
Expand Down
15 changes: 15 additions & 0 deletions shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,19 @@ export interface ILevel {
]
}

export interface IPlan {
id: number
hours: [string]
lessons: {
[key in Weekday]: [[IPlanEntry | null]]
}
}
export interface IPlanEntry {
name: string
teacher: string
room: string
}

export type CategoryName = "students" | "teachers"

export type Weekday = "monday" | "tuesday" | "wednesday" | "thursday" | "friday"
21 changes: 13 additions & 8 deletions src/apiCalls/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { ICategories } from "../../shared/types"
import { ICategories, IPlan } from "../../shared/types"

const API_ENDPOINT = `${location.protocol}//${location.hostname}:3000/`
const API_ENTRYPOINT = `${location.protocol}//${location.hostname}:3000/`

alert(API_ENDPOINT)
const fetchData = async (endpoint: string) => {
const response = await fetch(`${API_ENTRYPOINT}${endpoint}`)
if (!response.ok) {
throw new Error(`Could not fetch ${endpoint}, received ${response.status}`)
}
return response.json()
}

export const categories = () =>
fetch(API_ENDPOINT + "categories").then(res =>
res.json()
) as Promise<ICategories>
export const categories = () => fetchData("categories") as Promise<ICategories>

export default { categories }
export const plan = (id: number) => fetchData(`plans/${id}`) as Promise<IPlan>

export default { categories, plan }
11 changes: 6 additions & 5 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import React, { useState } from "react"

import { AppBar, Toolbar, Typography } from "@mui/material"

import { Weekday } from "../../shared/types"

import WeekdayTabs from "./WeekdayTabs"
import Categories from "./Categories"
import WeekdayTab from "./WeekdayTab"

const App = () => {
const [weekday, setWeekday] = useState("monday")
const handleWeekdayChange = (newValue: string) => {
const [weekday, setWeekday] = useState("monday" as Weekday)
const handleWeekdayChange = (newValue: Weekday) => {
setWeekday(newValue)
}

Expand All @@ -26,9 +29,7 @@ const App = () => {

<WeekdayTabs value={weekday} onChange={handleWeekdayChange} />

<Typography>
Selected plan id: {selectedPlanId} <br /> Selected weekday: {weekday}
</Typography>
<WeekdayTab planId={selectedPlanId} weekday={weekday} />
</React.Fragment>
)
}
Expand Down
3 changes: 3 additions & 0 deletions src/components/Categories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export default class Categories extends React.Component<
sx={whiteSelectStyle}
value={this.state.selectedLevel?.name}
onChange={this.handleLevelChange.bind(this)}
key="level"
>
{LevelSelectOptions}
</Select>
Expand All @@ -162,6 +163,7 @@ export default class Categories extends React.Component<
sx={whiteSelectStyle}
value={this.state.selectedPlan!.id}
onChange={this.handlePlanChange.bind(this)}
key="plan"
>
{PlanSelectOptions}
</Select>
Expand All @@ -183,6 +185,7 @@ export default class Categories extends React.Component<
sx={whiteSelectStyle}
value={this.state.selectedTeacher?.id}
onChange={this.handleTeacherChange.bind(this)}
key="teacher"
>
{TeacherSelectOptions}
</Select>
Expand Down
166 changes: 166 additions & 0 deletions src/components/WeekdayTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React from "react"

import {
Box,
Link,
Typography,
Table,
TableHead,
TableBody,
TableRow,
TableCell
} from "@mui/material"
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline"
import CircularProgress from "@mui/material/CircularProgress"

import { IPlan, IPlanEntry, Weekday } from "../../shared/types"
import apiCalls from "../apiCalls"

type Props = {
planId: number | null
weekday: Weekday
}

type State = {
displayedPlan: IPlan | null
loading: boolean
error: boolean
}

export default class WeekDayTab extends React.Component<Props, State> {
constructor(props: Props) {
super(props)

this.state = {
displayedPlan: null,
loading: false,
error: false
}
}

fetchPlanIfNeeded() {
if (this.props.planId === null) {
return
}

if (this.props.planId !== this.state.displayedPlan?.id) {
this.setState({
loading: true,
error: false
})

apiCalls
.plan(this.props.planId)
.then(plan => {
this.setState({
displayedPlan: plan,
loading: false
})
})
.catch(() => {
this.setState({
loading: false,
error: true
})
})
}
}

componentDidUpdate(prevProps: Props) {
if (prevProps.planId !== this.props.planId) {
this.setState({
loading: false,
error: false
})
this.fetchPlanIfNeeded()
}
}

componentDidMount() {
this.fetchPlanIfNeeded()
}

errorMessage = (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
pt: "64px",
px: "32px",
gap: "16px"
}}
>
<ErrorOutlineIcon sx={{ fontSize: "64px" }} />
<Typography textAlign="center">
Wystąpił błąd podczas ładowania planu. Spróbuj ponownie później.
</Typography>
<a href="https://zst-radom.edu.pl/plan_www/">
<Link
variant="button"
onClick={() => {
console.info("I'm a button.")
}}
>
Przejdź do starszej strony planu
</Link>
</a>
</Box>
)

loadingMessage = (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
pt: "64px",
px: "32px",
gap: "16px"
}}
>
<CircularProgress />
</Box>
)

render() {
if (this.state.error) {
return this.errorMessage
}

if (this.state.loading) {
return this.loadingMessage
}

console.log(this.state.displayedPlan)

return (
<Table>
<TableBody>
{this.state.displayedPlan?.hours.map((hour, i) => (
<TableRow key={hour}>
<TableCell>{hour}</TableCell>
<TableCell>
{this.state.displayedPlan?.lessons[this.props.weekday][i]
?.filter<IPlanEntry>(
(entry): entry is IPlanEntry => entry !== null
)
.map(entry => (
<Box
sx={{
display: "flex",
justifyContent: "space-between"
}}
>
<span>{entry.name}</span>
<span>{entry.room}</span>
</Box>
))}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}
}

0 comments on commit 4cfb353

Please sign in to comment.