Add fake login page until CAS access is granted #11
10
src/app.tsx
10
src/app.tsx
@ -4,7 +4,6 @@ import { route, routes } from "@/routing";
|
|||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { AppState, isReady } from "@/state/reducer";
|
import { AppState, isReady } from "@/state/reducer";
|
||||||
import { StudentActions } from "@/state/actions/student";
|
import { StudentActions } from "@/state/actions/student";
|
||||||
import { sampleStudent } from "@/provider/dummy/student";
|
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { Student } from "@/data";
|
import { Student } from "@/data";
|
||||||
import '@/styles/overrides.scss'
|
import '@/styles/overrides.scss'
|
||||||
@ -26,13 +25,6 @@ const UserMenu = (props: HTMLProps<HTMLUListElement>) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleUserLogin = () => {
|
|
||||||
dispatch({
|
|
||||||
type: StudentActions.Login,
|
|
||||||
student: sampleStudent,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleUserLogout = () => {
|
const handleUserLogout = () => {
|
||||||
dispatch({ type: StudentActions.Logout })
|
dispatch({ type: StudentActions.Logout })
|
||||||
}
|
}
|
||||||
@ -44,7 +36,7 @@ const UserMenu = (props: HTMLProps<HTMLUListElement>) => {
|
|||||||
{ ' ' }
|
{ ' ' }
|
||||||
(<Link to={ '#' } onClick={ handleUserLogout }>{ t('logout') }</Link>)
|
(<Link to={ '#' } onClick={ handleUserLogout }>{ t('logout') }</Link>)
|
||||||
</> : <>
|
</> : <>
|
||||||
<Link to={ '#' } onClick={ handleUserLogin }>{ t('login') }</Link>
|
<Link to={ route('user_login') }>{ t('login') }</Link>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
</ul>;
|
</ul>;
|
||||||
|
@ -284,7 +284,7 @@ export const InternshipForm: React.FunctionComponent = () => {
|
|||||||
postalCode: Yup.string().required(t("validation.required")),
|
postalCode: Yup.string().required(t("validation.required")),
|
||||||
building: Yup.string().required(t("validation.required")),
|
building: Yup.string().required(t("validation.required")),
|
||||||
kindOther: Yup.string().when("kind", {
|
kindOther: Yup.string().when("kind", {
|
||||||
is: (values: InternshipFormValues) => values?.kind !== InternshipType.Other,
|
is: (values: InternshipFormValues) => values?.kind === InternshipType.Other,
|
||||||
then: Yup.string().required(t("validation.required"))
|
then: Yup.string().required(t("validation.required"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -312,6 +312,8 @@ export const InternshipForm: React.FunctionComponent = () => {
|
|||||||
|
|
||||||
if (Object.keys(errors).length == 0) {
|
if (Object.keys(errors).length == 0) {
|
||||||
setConfirmDialogOpen(true);
|
setConfirmDialogOpen(true);
|
||||||
|
} else {
|
||||||
|
console.warn(errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { Page } from "@/pages/base";
|
import { Page } from "@/pages/base";
|
||||||
import { Button, Container, Stepper, Typography } from "@material-ui/core";
|
import { Button, Container, Stepper, Typography } from "@material-ui/core";
|
||||||
import { Link as RouterLink } from "react-router-dom";
|
import { Link as RouterLink, Redirect } from "react-router-dom";
|
||||||
import { route } from "@/routing";
|
import { route } from "@/routing";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
@ -11,23 +11,25 @@ import { Deadlines, Edition, getEditionDeadlines } from "@/data/edition";
|
|||||||
import { Step } from "@/components";
|
import { Step } from "@/components";
|
||||||
import { ProposalStep } from "@/pages/steps/proposal";
|
import { ProposalStep } from "@/pages/steps/proposal";
|
||||||
import { PlanStep } from "@/pages/steps/plan";
|
import { PlanStep } from "@/pages/steps/plan";
|
||||||
import { InsuranceStep } from "@/pages/steps/insurance";
|
|
||||||
import { InsuranceState } from "@/state/reducer/insurance";
|
import { InsuranceState } from "@/state/reducer/insurance";
|
||||||
|
import { InsuranceStep } from "@/pages/steps/insurance";
|
||||||
|
|
||||||
export const MainPage = () => {
|
export const MainPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const student = useSelector<AppState, Student | null>(state => state.student);
|
const student = useSelector<AppState, Student | null>(state => state.student);
|
||||||
|
|
||||||
const deadlines = useSelector<AppState, Deadlines>(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point
|
const deadlines = useSelector<AppState, Deadlines>(state => getEditionDeadlines(state.edition as Edition)); // edition cannot be null at this point
|
||||||
const insurance = useSelector<AppState, InsuranceState>(root => root.insurance);
|
const insurance = useSelector<AppState, InsuranceState>(root => root.insurance);
|
||||||
|
|
||||||
const missingStudentData = useMemo(() => student ? getMissingStudentData(student) : [], [student]);
|
const missingStudentData = useMemo(() => student ? getMissingStudentData(student) : [], [student]);
|
||||||
|
|
||||||
return <Page my={ 6 }>
|
if (!student) {
|
||||||
<Container>
|
return <Redirect to={ route("user_login") }/>;
|
||||||
<Typography variant="h2">{ t("pages.my-internship.header") }</Typography>
|
}
|
||||||
<Stepper orientation="vertical" nonLinear>
|
|
||||||
<Step label={ t('steps.personal-data.header') } completed={ missingStudentData.length === 0 } until={ deadlines.personalData }>
|
function *getSteps() {
|
||||||
|
yield <Step label={ t('steps.personal-data.header') } completed={ missingStudentData.length === 0 } until={ deadlines.personalData } key="personal-data">
|
||||||
{ missingStudentData.length > 0 && <>
|
{ missingStudentData.length > 0 && <>
|
||||||
<p>{ t('steps.personal-data.info') }</p>
|
<p>{ t('steps.personal-data.info') }</p>
|
||||||
|
|
||||||
@ -39,12 +41,23 @@ export const MainPage = () => {
|
|||||||
{ t('steps.personal-data.form') }
|
{ t('steps.personal-data.form') }
|
||||||
</Button>
|
</Button>
|
||||||
</> }
|
</> }
|
||||||
</Step>
|
</Step>;
|
||||||
<ProposalStep />
|
|
||||||
<PlanStep />
|
yield <ProposalStep key="proposal"/>;
|
||||||
{ insurance.required && <InsuranceStep /> }
|
yield <PlanStep key="plan"/>;
|
||||||
<Step label={ t('steps.report.header') } until={ deadlines.report }/>
|
|
||||||
<Step label={ t('steps.grade.header') }/>
|
if (insurance.required)
|
||||||
|
yield <InsuranceStep key="insurance"/>;
|
||||||
|
|
||||||
|
yield <Step label={ t('steps.report.header') } until={ deadlines.report } key="report"/>
|
||||||
|
yield <Step label={ t('steps.grade.header') } key="grade"/>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Page my={ 6 }>
|
||||||
|
<Container>
|
||||||
|
<Typography variant="h2">{ t("pages.my-internship.header") }</Typography>
|
||||||
|
<Stepper orientation="vertical" nonLinear>
|
||||||
|
{ Array.from(getSteps()) }
|
||||||
</Stepper>
|
</Stepper>
|
||||||
</Container>
|
</Container>
|
||||||
</Page>
|
</Page>
|
||||||
|
@ -13,11 +13,6 @@ export const InsuranceStep = () => {
|
|||||||
const deadline = useSelector<AppState, Moment | undefined>(state => getEditionDeadlines(state.edition as Edition).insurance); // edition cannot be null at this point
|
const deadline = useSelector<AppState, Moment | undefined>(state => getEditionDeadlines(state.edition as Edition).insurance); // edition cannot be null at this point
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// we don't want to show this step unless it's required
|
|
||||||
if (!insurance.required) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Step label={ t("steps.insurance.header") } until={ deadline } completed={ insurance.signed } active={ !insurance.signed }>
|
return <Step label={ t("steps.insurance.header") } until={ deadline } completed={ insurance.signed } active={ !insurance.signed }>
|
||||||
<p>{ t(`steps.insurance.instructions`) }</p>
|
<p>{ t(`steps.insurance.instructions`) }</p>
|
||||||
<Actions>
|
<Actions>
|
||||||
|
35
src/pages/user/login.tsx
Normal file
35
src/pages/user/login.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Page } from "@/pages/base";
|
||||||
|
import { Button, Container, Typography } from "@material-ui/core";
|
||||||
|
import { StudentActions, useDispatch } from "@/state/actions";
|
||||||
|
import { sampleStudent } from "@/provider/dummy";
|
||||||
|
import { useHistory } from "react-router-dom";
|
||||||
|
import { route } from "@/routing";
|
||||||
|
import { useVerticalSpacing } from "@/styles";
|
||||||
|
|
||||||
|
export const UserLoginPage = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const handleSampleLogin = () => {
|
||||||
|
dispatch({
|
||||||
|
type: StudentActions.Login,
|
||||||
|
student: sampleStudent,
|
||||||
|
})
|
||||||
|
|
||||||
|
history.push(route("home"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const classes = useVerticalSpacing(3);
|
||||||
|
|
||||||
|
return <Page>
|
||||||
|
<Page.Header maxWidth="md">
|
||||||
|
<Page.Title>Tu miało być przekierowanie do logowania PG...</Page.Title>
|
||||||
|
</Page.Header>
|
||||||
|
<Container maxWidth="md" className={ classes.root }>
|
||||||
|
<Typography variant="h3">... ale wciąż czekamy na dostęp :(</Typography>
|
||||||
|
|
||||||
|
<Button fullWidth onClick={ handleSampleLogin } variant="contained" color="primary">Zaloguj jako przykładowy student</Button>
|
||||||
|
</Container>
|
||||||
|
</Page>;
|
||||||
|
}
|
@ -4,10 +4,12 @@ import { RouteProps } from "react-router-dom";
|
|||||||
import { InternshipProposalFormPage, InternshipProposalPreviewPage } from "@/pages/internship/proposal";
|
import { InternshipProposalFormPage, InternshipProposalPreviewPage } from "@/pages/internship/proposal";
|
||||||
import { NotFoundPage } from "@/pages/errors/not-found";
|
import { NotFoundPage } from "@/pages/errors/not-found";
|
||||||
import SubmitPlanPage from "@/pages/internship/plan";
|
import SubmitPlanPage from "@/pages/internship/plan";
|
||||||
|
import { UserLoginPage } from "@/pages/user/login";
|
||||||
|
|
||||||
type Route = {
|
type Route = {
|
||||||
name?: string;
|
name?: string;
|
||||||
content: () => ReactComponentElement<any>,
|
content: () => ReactComponentElement<any>,
|
||||||
|
condition?: () => boolean,
|
||||||
} & RouteProps;
|
} & RouteProps;
|
||||||
|
|
||||||
export const routes: Route[] = [
|
export const routes: Route[] = [
|
||||||
@ -17,6 +19,9 @@ export const routes: Route[] = [
|
|||||||
{ name: "internship_proposal_preview", path: "/internship/preview/proposal", exact: true, content: () => <InternshipProposalPreviewPage/> },
|
{ name: "internship_proposal_preview", path: "/internship/preview/proposal", exact: true, content: () => <InternshipProposalPreviewPage/> },
|
||||||
{ name: "internship_plan", path: "/internship/plan", exact: true, content: () => <SubmitPlanPage/> },
|
{ name: "internship_plan", path: "/internship/plan", exact: true, content: () => <SubmitPlanPage/> },
|
||||||
|
|
||||||
|
// user
|
||||||
|
{ name: "user_login", path: "/user/login", exact: true, content: () => <UserLoginPage /> },
|
||||||
|
|
||||||
// fallback route for 404 pages
|
// fallback route for 404 pages
|
||||||
{ name: "fallback", path: "*", content: () => <NotFoundPage/> }
|
{ name: "fallback", path: "*", content: () => <NotFoundPage/> }
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { Reducer } from "react";
|
import { Reducer } from "react";
|
||||||
import { InsuranceAction, InsuranceActions } from "@/state/actions/insurance";
|
import { InsuranceAction, InsuranceActions } from "@/state/actions/insurance";
|
||||||
|
import { InternshipProposalAction, InternshipProposalActions } from "@/state/actions";
|
||||||
|
import { InternshipType } from "@/data";
|
||||||
|
|
||||||
export type InsuranceState = {
|
export type InsuranceState = {
|
||||||
required: boolean;
|
required: boolean;
|
||||||
@ -12,10 +14,21 @@ const initialInsuranceState: InsuranceState = {
|
|||||||
signed: false,
|
signed: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const insuranceReducer: Reducer<InsuranceState, InsuranceAction> = (state = initialInsuranceState, action) => {
|
export const insuranceReducer: Reducer<InsuranceState, InsuranceAction | InternshipProposalAction> = (state = initialInsuranceState, action) => {
|
||||||
const { type, ...payload } = action;
|
const { type, ...payload } = action;
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case InternshipProposalActions.Send:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
required: [
|
||||||
|
InternshipType.FreeApprenticeship,
|
||||||
|
InternshipType.FreeInternship,
|
||||||
|
InternshipType.PaidApprenticeship,
|
||||||
|
InternshipType.GraduateInternship,
|
||||||
|
].includes(action.internship.type)
|
||||||
|
}
|
||||||
|
|
||||||
case InsuranceActions.Signed:
|
case InsuranceActions.Signed:
|
||||||
return { ...state, signed: true }
|
return { ...state, signed: true }
|
||||||
case InsuranceActions.Update:
|
case InsuranceActions.Update:
|
||||||
|
@ -31,7 +31,7 @@ pages:
|
|||||||
my-internship:
|
my-internship:
|
||||||
header: "Moja praktyka"
|
header: "Moja praktyka"
|
||||||
proposal-form:
|
proposal-form:
|
||||||
header: "Propose internship"
|
header: "Zgłoszenie praktyki"
|
||||||
|
|
||||||
forms:
|
forms:
|
||||||
internship:
|
internship:
|
||||||
@ -138,7 +138,8 @@ steps:
|
|||||||
header: "Indywidualny Program Praktyki"
|
header: "Indywidualny Program Praktyki"
|
||||||
info:
|
info:
|
||||||
draft: >
|
draft: >
|
||||||
TODO
|
W porozumieniu z firmą w której odbywają się praktyki należy sporządzić Indywidualny Plan Praktyk zgodnie z
|
||||||
|
załączonym szablonem a następnie wysłać go do weryfikacji. (TODO)
|
||||||
awaiting: >
|
awaiting: >
|
||||||
Twój indywidualny program praktyki został poprawnie zapisany w systemie. Musi on jeszcze zostać zweryfikowany i
|
Twój indywidualny program praktyki został poprawnie zapisany w systemie. Musi on jeszcze zostać zweryfikowany i
|
||||||
zatwierdzony. Po weryfikacji zostaniesz poinformowany o akceptacji bądź konieczności wprowadzenia zmian.
|
zatwierdzony. Po weryfikacji zostaniesz poinformowany o akceptacji bądź konieczności wprowadzenia zmian.
|
||||||
@ -157,7 +158,7 @@ steps:
|
|||||||
insurance:
|
insurance:
|
||||||
header: "Ubezpieczenie NNW"
|
header: "Ubezpieczenie NNW"
|
||||||
instructions: >
|
instructions: >
|
||||||
papierki do podpisania...
|
Należy zgłosić się do pełnomocnika ds. praktyk Twojego kierunku i podpisać umowę ubezpieczenia. (TODO)
|
||||||
|
|
||||||
validation:
|
validation:
|
||||||
required: "To pole jest wymagane"
|
required: "To pole jest wymagane"
|
||||||
|
Loading…
Reference in New Issue
Block a user