From 411603e3a1859a5219f7c279e0c9bdc3aee9964e Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 3 Oct 2020 19:50:12 +0200 Subject: [PATCH] Add ability to fill student data --- src/api/{page.tsx => page.ts} | 0 src/api/student.ts | 6 ++ src/api/user.ts | 9 +- src/components/proposalPreview.tsx | 8 +- src/data/student.ts | 2 +- src/forms/user.tsx | 133 +++++++++++++++++++++++++++++ src/hooks/index.ts | 1 + src/hooks/state.ts | 18 ++++ src/middleware.tsx | 6 +- src/pages/base.tsx | 2 +- src/pages/main.tsx | 33 ++----- src/pages/steps/insurance.tsx | 11 +-- src/pages/steps/plan.tsx | 4 +- src/pages/steps/proposal.tsx | 4 +- src/pages/steps/student.tsx | 39 +++++++++ src/pages/user/fill.tsx | 31 +++++++ src/pages/user/login.tsx | 4 +- src/pages/user/profile.tsx | 58 +++++++++++++ src/routing.tsx | 6 +- src/serialization/edition.ts | 31 +++++++ src/serialization/index.ts | 1 + src/state/reducer/edition.ts | 5 +- src/state/store.ts | 2 +- translations/pl.yaml | 24 +++++- webpack.config.js | 2 +- 25 files changed, 382 insertions(+), 58 deletions(-) rename src/api/{page.tsx => page.ts} (100%) create mode 100644 src/forms/user.tsx create mode 100644 src/hooks/state.ts create mode 100644 src/pages/steps/student.tsx create mode 100644 src/pages/user/fill.tsx create mode 100644 src/pages/user/profile.tsx create mode 100644 src/serialization/edition.ts diff --git a/src/api/page.tsx b/src/api/page.ts similarity index 100% rename from src/api/page.tsx rename to src/api/page.ts diff --git a/src/api/student.ts b/src/api/student.ts index e93a861..49ad468 100644 --- a/src/api/student.ts +++ b/src/api/student.ts @@ -11,3 +11,9 @@ export async function current(): Promise { return studentDtoTransfer.transform(dto); } +export async function update(student: Student): Promise { + const dto = studentDtoTransfer.reverseTransform(student); + const response = await axios.put(CURRENT_STUDENT_ENDPOINT, dto); + + return student; +} diff --git a/src/api/user.ts b/src/api/user.ts index e930190..831c87b 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -1,13 +1,16 @@ import { axios } from "@/api/index"; import { query, route } from "@/routing"; -const LOGIN_ENDPOINT = "/access/login" +const LOGIN_ENDPOINT = "/access/login"; +const DEV_LOGIN_ENDPOINT = "/dev/login"; const CLIENT_ID = process.env.LOGIN_CLIENT_ID || "PraktykiClientId"; const AUTHORIZE_URL = process.env.AUTHORIZE || "https://logowanie.pg.edu.pl/oauth2.0/authorize"; -export async function login(code: string): Promise { - const response = await axios.get(LOGIN_ENDPOINT, { params: { code }}); +export async function login(code?: string): Promise { + const response = code + ? await axios.get(LOGIN_ENDPOINT, { params: { code }}) + : await axios.get(DEV_LOGIN_ENDPOINT); return response.data; } diff --git a/src/components/proposalPreview.tsx b/src/components/proposalPreview.tsx index 3babfc7..8a17cd0 100644 --- a/src/components/proposalPreview.tsx +++ b/src/components/proposalPreview.tsx @@ -6,6 +6,7 @@ import classNames from "classnames"; import { useVerticalSpacing } from "@/styles"; import moment from "moment"; import { Label, Section } from "@/components/section"; +import { StudentPreview } from "@/pages/user/profile"; export type ProposalPreviewProps = { proposal: Internship; @@ -19,12 +20,7 @@ export const ProposalPreview = ({ proposal }: ProposalPreviewProps) => { return
- { proposal.intern.name } { proposal.intern.surname } - - { t('internship.intern.semester', { semester: proposal.intern.semester }) } - { ", " } - { t('internship.intern.album', { album: proposal.intern.albumNumber }) } - +
diff --git a/src/data/student.ts b/src/data/student.ts index d649fbd..fe84901 100644 --- a/src/data/student.ts +++ b/src/data/student.ts @@ -23,6 +23,6 @@ export function getMissingStudentData(student: Student): (keyof Student)[] { !!student.email || "email", !!student.albumNumber || "albumNumber", !!student.semester || "semester", - !!student.course || "course", + // !!student.course || "course", ].filter(x => x !== true) as (keyof Student)[]; } diff --git a/src/forms/user.tsx b/src/forms/user.tsx new file mode 100644 index 0000000..9b450bc --- /dev/null +++ b/src/forms/user.tsx @@ -0,0 +1,133 @@ +import { Student } from "@/data"; +import { Transformer } from "@/serialization"; +import React, { useMemo } from "react"; +import { Field, Formik, useFormikContext } from "formik"; +import api from "@/api"; +import { Button, Grid, Typography } from "@material-ui/core"; +import { TextField as TextFieldFormik } from "formik-material-ui"; +import { useTranslation } from "react-i18next"; +import { Actions } from "@/components"; +import { Nullable } from "@/helpers"; +import * as Yup from "yup"; +import { StudentActions, useDispatch } from "@/state/actions"; + +interface StudentFormValues { + firstName: string; + lastName: string; + email: string; + albumNumber: number | ""; + semester: number | ""; +} + +type StudentFormProps = { + student: Student; +} + +const studentToFormValuesTransformer: Transformer, StudentFormValues, { current: Student }> = { + transform(subject: Nullable, context: { current: Student }): StudentFormValues { + return { + firstName: subject.name || "", + lastName: subject.surname || "", + albumNumber: subject.albumNumber || "", + semester: subject.semester || "", + email: subject.email || "", + }; + }, + reverseTransform(subject: StudentFormValues, { current }: { current: Student }): Nullable { + return { + ...current, + name: subject.firstName, + surname: subject.lastName, + albumNumber: subject.albumNumber ? subject.albumNumber : null, + semester: subject.semester ? subject.semester : null, + email: subject.email, + }; + }, +} + +export const StudentForm = ({ student }: StudentFormProps) => { + const { t } = useTranslation(); + const dispatch = useDispatch(); + + const validationSchema = useMemo(() => Yup.object({ + semester: Yup.number().required().min(1).max(10), + albumNumber: Yup.number().required(), + email: Yup.string().required(), + firstName: Yup.string().required(), + lastName: Yup.string().required(), + }), []); + + const initialValues: StudentFormValues = useMemo( + () => studentToFormValuesTransformer.transform(student, { current: student }), + [ student ] + ) + + + const handleFormSubmit = async (values: StudentFormValues) => { + const update = studentToFormValuesTransformer.reverseTransform(values, { current: student }) as Student; + const updated = await api.student.update(update); + + dispatch({ + type: StudentActions.Set, + student: updated, + }) + } + + + const InnerForm = () => { + const { handleSubmit } = useFormikContext(); + + return
+ { t("forms.student.sections.personal") } + + + + + + + + + + + + { t("forms.student.sections.studies")} + + + + + + + + + + + +
+ } + + return + + +} + +export default StudentForm; diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 848cfd7..544e1f0 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,3 +1,4 @@ export * from "./useProxyState" export * from "./useUpdateEffect" export * from "./useAsync" +export * from "./state" diff --git a/src/hooks/state.ts b/src/hooks/state.ts new file mode 100644 index 0000000..d024dcd --- /dev/null +++ b/src/hooks/state.ts @@ -0,0 +1,18 @@ +import { useSelector } from "react-redux"; +import { AppState } from "@/state/reducer"; +import { Edition, getEditionDeadlines } from "@/data/edition"; +import { editionSerializationTransformer } from "@/serialization"; +import { Student } from "@/data"; + +export const useCurrentStudent = () => useSelector( + state => state.student +) + +export const useCurrentEdition = () => useSelector( + state => state.edition && editionSerializationTransformer.reverseTransform(state.edition) +) + +export const useDeadlines = () => { + const edition = useCurrentEdition() as Edition; + return getEditionDeadlines(edition); +} diff --git a/src/middleware.tsx b/src/middleware.tsx index 1bb00b0..166de95 100644 --- a/src/middleware.tsx +++ b/src/middleware.tsx @@ -9,7 +9,7 @@ export const isReadyMiddleware: Middleware = next => isLoggedInMiddlew const ready = useSelector(isReady); if (ready) { - return next(); + return <>{ next() }; } return ; @@ -19,8 +19,8 @@ export const isLoggedInMiddleware: Middleware = next => { const user = useSelector(state => state.user) as UserState; if (user.loggedIn) { - return next(); + return <>{ next() }; } - return ; + return ; } diff --git a/src/pages/base.tsx b/src/pages/base.tsx index be27987..bc6e5cc 100644 --- a/src/pages/base.tsx +++ b/src/pages/base.tsx @@ -21,7 +21,7 @@ export const Page = ({ title, children, ...props }: PageProps) => { } -Page.Header = ({ children, maxWidth = false, ...props }: PageHeaderProps) => +Page.Header = ({ children, maxWidth = undefined, ...props }: PageHeaderProps) =>
{ children } diff --git a/src/pages/main.tsx b/src/pages/main.tsx index 28215eb..e6d9cf2 100644 --- a/src/pages/main.tsx +++ b/src/pages/main.tsx @@ -1,51 +1,34 @@ -import React, { useEffect, useMemo } from "react"; +import React from "react"; import { Page } from "@/pages/base"; -import { Button, Container, Stepper, Typography } from "@material-ui/core"; -import { Link as RouterLink, Redirect } from "react-router-dom"; +import { Container, Stepper, Typography } from "@material-ui/core"; +import { Redirect } from "react-router-dom"; import { route } from "@/routing"; import { useTranslation } from "react-i18next"; import { useSelector } from "react-redux"; import { AppState } from "@/state/reducer"; -import { getMissingStudentData, Student } from "@/data"; -import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition"; +import { Student } from "@/data"; import { Step } from "@/components"; import { ProposalStep } from "@/pages/steps/proposal"; import { PlanStep } from "@/pages/steps/plan"; import { InsuranceState } from "@/state/reducer/insurance"; import { InsuranceStep } from "@/pages/steps/insurance"; -import api from "@/api"; +import { StudentStep } from "@/pages/steps/student"; +import { useDeadlines } from "@/hooks"; export const MainPage = () => { const { t } = useTranslation(); const student = useSelector(state => state.student); - const deadlines = useSelector(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point + const deadlines = useDeadlines(); const insurance = useSelector(root => root.insurance); - const missingStudentData = useMemo(() => student ? getMissingStudentData(student) : [], [student]); - - useEffect(() => void api.edition.available()) - if (!student) { return ; } function *getSteps() { - yield - { missingStudentData.length > 0 && <> -

{ t('steps.personal-data.info') }

- -
    - { missingStudentData.map(field =>
  • { t(`student.${ field }`) }
  • ) } -
- - - } -
; - + yield ; yield ; yield ; diff --git a/src/pages/steps/insurance.tsx b/src/pages/steps/insurance.tsx index 56e1a41..b005389 100644 --- a/src/pages/steps/insurance.tsx +++ b/src/pages/steps/insurance.tsx @@ -4,16 +4,17 @@ import { InsuranceState } from "@/state/reducer/insurance"; import { Actions, Step } from "@/components"; import { useTranslation } from "react-i18next"; import React from "react"; -import { Edition, getEditionDeadlines } from "@/data/edition"; -import { Moment } from "moment"; import { ContactAction } from "@/pages/steps/common"; +import { useDeadlines } from "@/hooks"; +import { StepProps } from "@material-ui/core"; -export const InsuranceStep = () => { +export const InsuranceStep = (props: StepProps) => { const insurance = useSelector(root => root.insurance); - const deadline = useSelector(state => getEditionDeadlines(state.edition as Edition).insurance); // edition cannot be null at this point + const deadline = useDeadlines().insurance; + const { t } = useTranslation(); - return + return

{ t(`steps.insurance.instructions`) }

diff --git a/src/pages/steps/plan.tsx b/src/pages/steps/plan.tsx index 7a94c7f..e6f6c4c 100644 --- a/src/pages/steps/plan.tsx +++ b/src/pages/steps/plan.tsx @@ -9,9 +9,9 @@ import { Link as RouterLink } from "react-router-dom"; import { Actions, Step } from "@/components"; import React, { HTMLProps } from "react"; import { Alert, AlertTitle } from "@material-ui/lab"; -import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition"; import { ContactAction, Status } from "@/pages/steps/common"; import { Description as DescriptionIcon } from "@material-ui/icons"; +import { useDeadlines } from "@/hooks"; const PlanActions = () => { const status = useSelector(state => getSubmissionStatus(state.plan)); @@ -74,7 +74,7 @@ export const PlanStep = (props: StepProps) => { const submission = useSelector(state => state.plan); const status = getSubmissionStatus(submission); - const deadlines = useSelector(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point + const deadlines = useDeadlines(); const { sent, declined, comment } = submission; diff --git a/src/pages/steps/proposal.tsx b/src/pages/steps/proposal.tsx index f7646d9..9996ba4 100644 --- a/src/pages/steps/proposal.tsx +++ b/src/pages/steps/proposal.tsx @@ -6,12 +6,12 @@ import React, { HTMLProps } from "react"; import { InternshipProposalState } from "@/state/reducer/proposal"; import { Alert, AlertTitle } from "@material-ui/lab"; import { Box, Button, ButtonProps, StepProps } from "@material-ui/core"; -import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition"; import { Actions, Step } from "@/components"; import { route } from "@/routing"; import { Link as RouterLink } from "react-router-dom"; import { ClipboardEditOutline, FileFind } from "mdi-material-ui/index"; import { ContactAction, Status } from "@/pages/steps/common"; +import { useDeadlines } from "@/hooks"; const ProposalActions = () => { const status = useSelector(state => getSubmissionStatus(state.proposal)); @@ -69,7 +69,7 @@ export const ProposalStep = (props: StepProps) => { const submission = useSelector(state => state.proposal); const status = useSelector(state => getSubmissionStatus(state.proposal)); - const deadlines = useSelector(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point + const deadlines = useDeadlines(); const { sent, declined, comment } = submission; diff --git a/src/pages/steps/student.tsx b/src/pages/steps/student.tsx new file mode 100644 index 0000000..24eab0b --- /dev/null +++ b/src/pages/steps/student.tsx @@ -0,0 +1,39 @@ +import { Button, StepProps } from "@material-ui/core"; +import { route } from "@/routing"; +import { Link as RouterLink } from "react-router-dom"; +import { Actions, Step } from "@/components"; +import React, { useMemo } from "react"; +import { useTranslation } from "react-i18next"; +import { getMissingStudentData, Student } from "@/data"; +import { useSelector } from "react-redux"; +import { AppState } from "@/state/reducer"; +import { useDeadlines } from "@/hooks"; +import { AccountDetails } from "mdi-material-ui"; + +export const StudentStep = (props: StepProps) => { + const { t } = useTranslation(); + const student = useSelector(state => state.student); + const missingStudentData = useMemo(() => student ? getMissingStudentData(student) : [], [student]); + const deadlines = useDeadlines(); + + return + { missingStudentData.length > 0 ? <> +

{ t('steps.personal-data.info') }

+ +
    + { missingStudentData.map(field =>
  • { t(`student.${ field }`) }
  • ) } +
+ + + : <> +

{ t('steps.personal-data.all-filled') }

+ + + + } +
+} diff --git a/src/pages/user/fill.tsx b/src/pages/user/fill.tsx new file mode 100644 index 0000000..de3cc1c --- /dev/null +++ b/src/pages/user/fill.tsx @@ -0,0 +1,31 @@ +import { useSelector } from "react-redux"; +import { AppState } from "@/state/reducer"; +import React from "react"; +import { Page } from "@/pages/base"; +import { useTranslation } from "react-i18next"; +import { Container, Link, Typography } from "@material-ui/core"; +import StudentForm from "@/forms/user"; +import { Student } from "@/data"; +import { Link as RouterLink } from "react-router-dom"; +import { route } from "@/routing"; + +export const UserFillPage = () => { + const student = useSelector(state => state.student) as Student; + + const { t } = useTranslation(); + + return + + + { t("pages.my-internship.header") } + { t("pages.user-fill.title") } + + { t("pages.user-fill.title") } + + + + + +} + +export default UserFillPage; diff --git a/src/pages/user/login.tsx b/src/pages/user/login.tsx index 46a5a00..c7dd466 100644 --- a/src/pages/user/login.tsx +++ b/src/pages/user/login.tsx @@ -11,7 +11,7 @@ import api from "@/api"; import { UserActions } from "@/state/actions/user"; import { getAuthorizeUrl } from "@/api/user"; -const authorizeUser = (code: string) => async (dispatch: Dispatch, getState: () => AppState): Promise => { +const authorizeUser = (code?: string) => async (dispatch: Dispatch, getState: () => AppState): Promise => { const token = await api.user.login(code); dispatch({ @@ -34,7 +34,7 @@ export const UserLoginPage = () => { const query = new URLSearchParams(useLocation().search); const handleSampleLogin = async () => { - await dispatch(authorizeUser("test")); + await dispatch(authorizeUser()); history.push(route("home")); } diff --git a/src/pages/user/profile.tsx b/src/pages/user/profile.tsx new file mode 100644 index 0000000..5ebc8ba --- /dev/null +++ b/src/pages/user/profile.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { Page } from "@/pages/base"; +import { useTranslation } from "react-i18next"; +import { useCurrentStudent } from "@/hooks"; +import { Box, Button, Container, Link, Paper, Typography } from "@material-ui/core"; +import { Student } from "@/data"; +import { Link as RouterLink } from "react-router-dom"; +import { route } from "@/routing"; +import { Actions } from "@/components"; +import { useVerticalSpacing } from "@/styles"; + +type StudentPreviewProps = { + student: Student; +} + +export const StudentPreview = ({ student }: StudentPreviewProps) => { + const { t } = useTranslation(); + + return <> + { student.name } { student.surname } + + { t('internship.intern.semester', { semester: student.semester }) } + { ", " } + { t('internship.intern.album', { album: student.albumNumber }) } + + ; +} + +export const UserProfilePage = () => { + const { t } = useTranslation(); + + const student = useCurrentStudent() as Student; + const spacing = useVerticalSpacing(3); + + return + + + { t("pages.my-internship.header") } + { t("pages.user-profile.title") } + + { t('pages.user-profile.title') } + + + + + + + + + + + + +} + +export default UserProfilePage; diff --git a/src/routing.tsx b/src/routing.tsx index 2a5eddd..f7d37e5 100644 --- a/src/routing.tsx +++ b/src/routing.tsx @@ -8,6 +8,8 @@ import { UserLoginPage } from "@/pages/user/login"; import { RegisterEditionPage } from "@/pages/edition/register"; import PickEditionPage from "@/pages/edition/pick"; import { isLoggedInMiddleware, isReadyMiddleware } from "@/middleware"; +import UserFillPage from "@/pages/user/fill"; +import UserProfilePage from "@/pages/user/profile"; type Route = { name?: string; @@ -30,7 +32,7 @@ export function processMiddlewares(middleware: Middleware , middlewares: [ isLoggedInMiddleware ] }, + { name: "home", path: "/", exact: true, content: () => , middlewares: [ isReadyMiddleware ] }, // edition { name: "edition_register", path: "/edition/register", exact: true, content: () => , middlewares: [ isLoggedInMiddleware ] }, @@ -43,6 +45,8 @@ export const routes: Route[] = [ // user { name: "user_login", path: "/user/login", content: () => }, + { name: "user_fill", path: "/user/data", content: () => , middlewares: [ isLoggedInMiddleware ] }, + { name: "user_profile", path: "/user/profile", content: () => , middlewares: [ isLoggedInMiddleware ] }, // fallback route for 404 pages { name: "fallback", path: "*", content: () => } diff --git a/src/serialization/edition.ts b/src/serialization/edition.ts new file mode 100644 index 0000000..ae4555c --- /dev/null +++ b/src/serialization/edition.ts @@ -0,0 +1,31 @@ +import { Serializable, SerializationTransformer } from "@/serialization/types"; +import { Edition } from "@/data/edition"; +import { momentSerializationTransformer } from "@/serialization/moment"; +import { Moment } from "moment"; + +export const editionSerializationTransformer: SerializationTransformer = { + transform(subject: Edition, context?: unknown): Serializable { + return { + course: subject.course, + minimumInternshipHours: subject.minimumInternshipHours, + maximumInternshipHours: subject.maximumInternshipHours, + proposalDeadline: momentSerializationTransformer.transform(subject.proposalDeadline), + reportingEnd: momentSerializationTransformer.transform(subject.reportingEnd), + reportingStart: momentSerializationTransformer.transform(subject.reportingStart), + startDate: momentSerializationTransformer.transform(subject.startDate), + endDate: momentSerializationTransformer.transform(subject.endDate), + } + }, + reverseTransform(subject: Serializable, context?: unknown): Edition { + return { + course: subject.course, + minimumInternshipHours: subject.minimumInternshipHours, + maximumInternshipHours: subject.maximumInternshipHours, + proposalDeadline: momentSerializationTransformer.reverseTransform(subject.proposalDeadline) as Moment, + reportingEnd: momentSerializationTransformer.reverseTransform(subject.reportingEnd) as Moment, + reportingStart: momentSerializationTransformer.reverseTransform(subject.reportingStart) as Moment, + startDate: momentSerializationTransformer.reverseTransform(subject.startDate) as Moment, + endDate: momentSerializationTransformer.reverseTransform(subject.endDate) as Moment, + } + }, +} diff --git a/src/serialization/index.ts b/src/serialization/index.ts index e6efcb2..1f6c52f 100644 --- a/src/serialization/index.ts +++ b/src/serialization/index.ts @@ -1,3 +1,4 @@ export * from "./internship" export * from "./moment" export * from "./types" +export * from "./edition" diff --git a/src/state/reducer/edition.ts b/src/state/reducer/edition.ts index ef696f9..93847c2 100644 --- a/src/state/reducer/edition.ts +++ b/src/state/reducer/edition.ts @@ -1,14 +1,15 @@ import { Edition } from "@/data/edition"; import { EditionAction, EditionActions } from "@/state/actions/edition"; +import { editionSerializationTransformer, Serializable } from "@/serialization"; -export type EditionState = Edition | null; +export type EditionState = Serializable | null; const initialEditionState: EditionState = null; const editionReducer = (state: EditionState = initialEditionState, action: EditionAction): EditionState => { switch (action.type) { case EditionActions.Set: - return action.edition; + return editionSerializationTransformer.transform(action.edition); } return state; diff --git a/src/state/store.ts b/src/state/store.ts index 935b3b2..7168bf7 100644 --- a/src/state/store.ts +++ b/src/state/store.ts @@ -10,7 +10,7 @@ const store = createStore( { key: 'state', storage: sessionStorage, - blacklist: ['edition'] + blacklist: [] }, rootReducer ), diff --git a/translations/pl.yaml b/translations/pl.yaml index 2d7554f..d077211 100644 --- a/translations/pl.yaml +++ b/translations/pl.yaml @@ -11,7 +11,7 @@ left: jeszcze {{ left, humanize }} confirm: zatwierdź go-back: wstecz - +save: zapisz make-changes: wprowadź zmiany review: podgląd fix-errors: popraw uwagi @@ -39,8 +39,22 @@ pages: my-editions: "Moje praktyki" pick: "wybierz" register: "Zapisz się do edycji praktyk" + user-fill: + title: "Uzupełnij swoje dane" + user-profile: + title: "Moje dane" forms: + student: + fields: + first-name: Imię + last-name: Nazwisko + email: Kontaktowy adres e-mail + album-number: Numer albumu + semester: Aktualny semestr studiów + sections: + personal: "Dane osobowe" + studies: "Dane kierunkowe" internship: fields: start-date: Data rozpoczęcia praktyki @@ -127,11 +141,15 @@ internship: steps: personal-data: - header: "Uzupełnienie informacji" + header: "Uzupełnienie danych" info: > Twój profil jest niekompletny. W celu kontynuacji praktyki musisz uzupełnić informacje podane poniżej. Jeżeli masz problem z uzupełnieniem tych informacji - skontaktuj się z pełnomocnikiem ds. praktyk dla Twojego kierunku. - form: "Uzupełnij dane" + all-filled: > + Wypełniłeś wszystkie wymagane informacje o sobie. + actions: + form: "Uzupełnij dane" + info: $t(pages.user-profile.title) internship-proposal: header: "Zgłoszenie praktyki" info: diff --git a/webpack.config.js b/webpack.config.js index 6585967..201baa4 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -59,7 +59,7 @@ const config = { port: parseInt(process.env.APP_PORT || "3000"), proxy: { "/api": { - target: "http://system-praktyk-front.localhost:8080/", + target: "https://system-praktyk.stg.kadet.net/api/", changeOrigin: true, pathRewrite: { "^/api": ''