From 379acad8c5a5a2d9a29b5e89f9324f53df54d6d1 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sun, 27 Sep 2020 22:06:53 +0200 Subject: [PATCH] Login and stuff --- src/api/dto/course.ts | 23 +++++++++++ src/api/dto/edition.ts | 57 +++++++++++++++++++++++++++ src/api/dto/student.ts | 34 +++++++++++++++++ src/api/edition.ts | 18 ++++----- src/api/index.ts | 4 +- src/api/student.ts | 13 +++++++ src/app.tsx | 20 ++++------ src/components/section.tsx | 2 + src/data/edition.ts | 5 ++- src/data/student.ts | 2 +- src/helpers.ts | 2 +- src/hooks/useAsync.ts | 10 ++++- src/middleware.tsx | 15 ++++++++ src/pages/edition/pick.tsx | 72 +++++++++++++++++++++++++++++++++++ src/pages/main.tsx | 2 +- src/pages/user/login.tsx | 32 ++++++++++++---- src/provider/dummy/student.ts | 2 +- src/routing.tsx | 29 +++++++++++--- src/serialization/types.ts | 7 +++- src/state/actions/edition.ts | 2 +- src/state/actions/index.ts | 21 +++++++++- src/state/actions/student.ts | 13 +++++++ src/state/actions/user.ts | 2 - src/state/reducer/student.ts | 5 ++- translations/pl.yaml | 5 +++ webpack.config.js | 1 + 26 files changed, 344 insertions(+), 54 deletions(-) create mode 100644 src/api/dto/course.ts create mode 100644 src/api/dto/edition.ts create mode 100644 src/api/dto/student.ts create mode 100644 src/api/student.ts create mode 100644 src/middleware.tsx create mode 100644 src/pages/edition/pick.tsx create mode 100644 src/state/actions/student.ts diff --git a/src/api/dto/course.ts b/src/api/dto/course.ts new file mode 100644 index 0000000..8b13f1f --- /dev/null +++ b/src/api/dto/course.ts @@ -0,0 +1,23 @@ +import { Course, Identifiable } from "@/data"; +import { Transformer } from "@/serialization"; + +export interface CourseDTO extends Identifiable { + name: string; +} + +export const courseDtoTransformer: Transformer = { + reverseTransform(subject: Course, context: undefined): CourseDTO { + return { + id: subject.id, + name: subject.name, + }; + }, + transform(subject: CourseDTO, context: undefined): Course { + return { + id: subject.id, + name: subject.name, + desiredSemesters: [], + possibleProgramEntries: [], // todo + }; + } +} diff --git a/src/api/dto/edition.ts b/src/api/dto/edition.ts new file mode 100644 index 0000000..94c3101 --- /dev/null +++ b/src/api/dto/edition.ts @@ -0,0 +1,57 @@ +import { Identifiable } from "@/data"; +import { CourseDTO, courseDtoTransformer } from "@/api/dto/course"; +import { OneWayTransformer, Transformer } from "@/serialization"; +import { Edition } from "@/data/edition"; +import moment from "moment"; +import { Subset } from "@/helpers"; + +export interface EditionDTO extends Identifiable { + editionStart: string, + editionFinish: string, + reportingStart: string, + course: CourseDTO, +} + +export interface EditionTeaserDTO extends Identifiable { + editionStart: string, + editionFinish: string, + courseName: string, +} + +export const editionTeaserDtoTransformer: OneWayTransformer> = { + transform(subject: EditionTeaserDTO, context?: undefined): Subset { + return { + id: subject.id, + startDate: moment(subject.editionStart), + endDate: moment(subject.editionFinish), + course: { + name: subject.courseName, + } + } + } +} + +export const editionDtoTransformer: Transformer = { + reverseTransform(subject: Edition, context: undefined): EditionDTO { + return { + id: subject.id, + editionFinish: subject.endDate.toISOString(), + editionStart: subject.startDate.toISOString(), + course: courseDtoTransformer.reverseTransform(subject.course), + reportingStart: subject.reportingStart.toISOString(), + }; + }, + transform(subject: EditionDTO, context: undefined): Edition { + return { + id: subject.id, + course: courseDtoTransformer.transform(subject.course), + startDate: moment(subject.editionStart), + endDate: moment(subject.editionFinish), + minimumInternshipHours: 40, + maximumInternshipHours: 160, + proposalDeadline: moment(subject.reportingStart), + reportingStart: moment(subject.reportingStart), + reportingEnd: moment(subject.reportingStart).add(1, 'month'), + }; + } +} diff --git a/src/api/dto/student.ts b/src/api/dto/student.ts new file mode 100644 index 0000000..269e1aa --- /dev/null +++ b/src/api/dto/student.ts @@ -0,0 +1,34 @@ +import { Identifiable, Student } from "@/data"; +import { Transformer } from "@/serialization"; + +export interface StudentDTO extends Identifiable { + albumNumber: number, + course: any, + email: string, + firstName: string, + lastName: string, + semester: number, +} + +export const studentDtoTransfer: Transformer = { + reverseTransform(subject: Student, context: undefined): StudentDTO { + return { + albumNumber: subject.albumNumber, + course: subject.course, + email: subject.email, + firstName: subject.name, + lastName: subject.surname, + semester: subject.semester + }; + }, + transform(subject: StudentDTO, context: undefined): Student { + return { + albumNumber: subject.albumNumber, + course: subject.course, + email: subject.email, + name: subject.firstName, + semester: subject.semester, + surname: subject.lastName + }; + } +} diff --git a/src/api/edition.ts b/src/api/edition.ts index bce8982..6164634 100644 --- a/src/api/edition.ts +++ b/src/api/edition.ts @@ -1,16 +1,16 @@ import { axios } from "@/api/index"; import { Edition } from "@/data/edition"; -import { sampleEdition } from "@/provider/dummy"; -import { delay } from "@/helpers"; +import { prepare } from "@/routing"; +import { EditionDTO, editionDtoTransformer, editionTeaserDtoTransformer } from "@/api/dto/edition"; const EDITIONS_ENDPOINT = "/editions"; const EDITION_INFO_ENDPOINT = "/editions/:key"; const REGISTER_ENDPOINT = "/register"; -export async function editions() { +export async function available() { const response = await axios.get(EDITIONS_ENDPOINT); - return response.data; + return (response.data || []).map(editionTeaserDtoTransformer.transform); } export async function join(key: string): Promise { @@ -23,13 +23,9 @@ export async function join(key: string): Promise { } } -// MOCK export async function get(key: string): Promise { - await delay(Math.random() * 200 + 100); + const response = await axios.get(prepare(EDITION_INFO_ENDPOINT, { key })); + const dto = response.data; - if (key == "inf2020") { - return sampleEdition; - } - - return null; + return editionDtoTransformer.transform(dto); } diff --git a/src/api/index.ts b/src/api/index.ts index 6d9942d..3432330 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -6,6 +6,7 @@ import { UserState } from "@/state/reducer/user"; import * as user from "./user"; import * as edition from "./edition"; import * as page from "./page" +import * as student from "./student" export const axios = Axios.create({ baseURL: process.env.API_BASE_URL || "https://system-praktyk.stg.kadet.net/api/", @@ -31,7 +32,8 @@ axios.interceptors.request.use(config => { const api = { user, edition, - page + page, + student } export default api; diff --git a/src/api/student.ts b/src/api/student.ts new file mode 100644 index 0000000..e93a861 --- /dev/null +++ b/src/api/student.ts @@ -0,0 +1,13 @@ +import { axios } from "@/api/index"; +import { Student } from "@/data/student"; +import { StudentDTO, studentDtoTransfer } from "@/api/dto/student"; + +export const CURRENT_STUDENT_ENDPOINT = '/students/current'; + +export async function current(): Promise { + const response = await axios.get(CURRENT_STUDENT_ENDPOINT); + const dto = response.data; + + return studentDtoTransfer.transform(dto); +} + diff --git a/src/app.tsx b/src/app.tsx index c05b38c..a3bb940 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,16 +1,14 @@ import React, { HTMLProps, useEffect } from 'react'; import { Link, Route, Switch } from "react-router-dom" -import { route, routes } from "@/routing"; +import { processMiddlewares, route, routes } from "@/routing"; import { useSelector } from "react-redux"; -import { AppState, isReady } from "@/state/reducer"; +import { AppState } from "@/state/reducer"; import { Trans, useTranslation } from "react-i18next"; import { Student } from "@/data"; import '@/styles/overrides.scss' import '@/styles/header.scss' import '@/styles/footer.scss' import classNames from "classnames"; -import { EditionActions } from "@/state/actions/edition"; -import { sampleEdition } from "@/provider/dummy/edition"; import { Edition } from "@/data/edition"; import { SettingActions } from "@/state/actions/settings"; import { useDispatch, UserActions } from "@/state/actions"; @@ -68,20 +66,12 @@ function App() { const { t } = useTranslation(); const locale = useSelector(state => getLocale(state.settings)); - useEffect(() => { - if (!edition) { - dispatch({ type: EditionActions.Set, edition: sampleEdition }); - } - }) - useEffect(() => { i18n.changeLanguage(locale); document.documentElement.lang = locale; moment.locale(locale) }, [ locale ]) - const ready = useSelector(isReady); - return <>
- { ready && { routes.map(({ name, content, ...route }) => { content() }) } } + { + { routes.map(({ name, content, middlewares = [], ...route }) => + { processMiddlewares([ ...middlewares, content ]) } + ) } + }