Allow overriding of state for testing purposes.
This commit is contained in:
parent
0ff80a454d
commit
c13d880baa
@ -6,6 +6,7 @@ import { InternshipTypeDTO, internshipTypeDtoTransformer } from "@/api/dto/type"
|
|||||||
import { Moment } from "moment-timezone";
|
import { Moment } from "moment-timezone";
|
||||||
import { sampleStudent } from "@/provider/dummy";
|
import { sampleStudent } from "@/provider/dummy";
|
||||||
import { UploadType } from "@/api/upload";
|
import { UploadType } from "@/api/upload";
|
||||||
|
import { ProgramEntryDTO, programEntryDtoTransformer } from "@/api/dto/edition";
|
||||||
|
|
||||||
export enum SubmissionState {
|
export enum SubmissionState {
|
||||||
Draft = "Draft",
|
Draft = "Draft",
|
||||||
@ -48,6 +49,7 @@ export interface InternshipRegistrationDTO extends Identifiable {
|
|||||||
company: Company,
|
company: Company,
|
||||||
branchAddress: Office,
|
branchAddress: Office,
|
||||||
declaredHours: number,
|
declaredHours: number,
|
||||||
|
subjects: { subject: ProgramEntryDTO }[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InternshipDocument extends Identifiable {
|
export interface InternshipDocument extends Identifiable {
|
||||||
@ -99,7 +101,7 @@ export const internshipRegistrationDtoTransformer: OneWayTransformer<InternshipR
|
|||||||
hours: dto.declaredHours,
|
hours: dto.declaredHours,
|
||||||
isAccepted: dto.state === SubmissionState.Accepted,
|
isAccepted: dto.state === SubmissionState.Accepted,
|
||||||
lengthInWeeks: 0,
|
lengthInWeeks: 0,
|
||||||
program: [],
|
program: dto.subjects.map(subject => programEntryDtoTransformer.transform(subject.subject)),
|
||||||
intern: sampleStudent, // fixme
|
intern: sampleStudent, // fixme
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,43 @@
|
|||||||
import { InternshipInfoDTO, InternshipRegistrationUpdate } from "@/api/dto/internship-registration";
|
import { InternshipInfoDTO, InternshipRegistrationUpdate, SubmissionState } from "@/api/dto/internship-registration";
|
||||||
import { axios } from "@/api/index";
|
import { axios } from "@/api/index";
|
||||||
import { Nullable } from "@/helpers";
|
import { Nullable } from "@/helpers";
|
||||||
|
|
||||||
const INTERNSHIP_REGISTRATION_ENDPOINT = '/internshipRegistration';
|
const INTERNSHIP_REGISTRATION_ENDPOINT = '/internshipRegistration';
|
||||||
const INTERNSHIP_ENDPOINT = '/internship';
|
const INTERNSHIP_ENDPOINT = '/internship';
|
||||||
|
|
||||||
export async function update(internship: Nullable<InternshipRegistrationUpdate>): Promise<boolean> {
|
export type ValidationMessage = {
|
||||||
await axios.put(INTERNSHIP_REGISTRATION_ENDPOINT, internship);
|
key: string;
|
||||||
|
parameters: { [name: string]: string },
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
export class ValidationError extends Error {
|
||||||
|
public readonly messages: ValidationMessage[];
|
||||||
|
|
||||||
|
constructor(messages: ValidationMessage[], message: string = "There were validation errors.") {
|
||||||
|
super(message);
|
||||||
|
Object.setPrototypeOf(this, ValidationError.prototype);
|
||||||
|
|
||||||
|
this.messages = messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UpdateResponse {
|
||||||
|
status: SubmissionState;
|
||||||
|
errors?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function update(internship: Nullable<InternshipRegistrationUpdate>): Promise<SubmissionState> {
|
||||||
|
const response = (await axios.put<UpdateResponse>(INTERNSHIP_REGISTRATION_ENDPOINT, internship)).data;
|
||||||
|
|
||||||
|
if (response.status == SubmissionState.Draft) {
|
||||||
|
throw new ValidationError(
|
||||||
|
response.errors?.map(
|
||||||
|
msg => ({ key: msg, parameters: {} })
|
||||||
|
) || []
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(): Promise<InternshipInfoDTO> {
|
export async function get(): Promise<InternshipInfoDTO> {
|
||||||
|
@ -88,7 +88,7 @@ function App() {
|
|||||||
<nav className="header__bottom">
|
<nav className="header__bottom">
|
||||||
<ul className="header__menu header__menu--main">
|
<ul className="header__menu header__menu--main">
|
||||||
<li><Link to={ route("home") }>{ t("pages.my-internship.header") }</Link></li>
|
<li><Link to={ route("home") }>{ t("pages.my-internship.header") }</Link></li>
|
||||||
<li><Link to="/regulamin">Regulamin</Link></li>
|
<li><Link to="/regulations">Regulamin</Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { Internship } from "@/data";
|
import { Internship } from "@/data";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Typography } from "@material-ui/core";
|
import { List, Typography, ListItem, ListItemIcon, ListItemText } from "@material-ui/core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useVerticalSpacing } from "@/styles";
|
import { useVerticalSpacing } from "@/styles";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { Label, Section } from "@/components/section";
|
import { Label, Section } from "@/components/section";
|
||||||
import { StudentPreview } from "@/pages/user/profile";
|
import { StudentPreview } from "@/pages/user/profile";
|
||||||
|
import { Check, StickerCheck } from "mdi-material-ui";
|
||||||
|
|
||||||
export type ProposalPreviewProps = {
|
export type ProposalPreviewProps = {
|
||||||
proposal: Internship;
|
proposal: Internship;
|
||||||
@ -42,6 +43,16 @@ export const ProposalPreview = ({ proposal }: ProposalPreviewProps) => {
|
|||||||
<Typography className="proposal__primary">{ proposal.type.label.pl }</Typography>
|
<Typography className="proposal__primary">{ proposal.type.label.pl }</Typography>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
<Section>
|
||||||
|
<Label>{ t('internship.sections.program') }</Label>
|
||||||
|
<List>
|
||||||
|
{ proposal.program.map(subject => <ListItem key={ subject.id }>
|
||||||
|
<ListItemIcon><StickerCheck /></ListItemIcon>
|
||||||
|
<ListItemText>{ subject.description }</ListItemText>
|
||||||
|
</ListItem>) }
|
||||||
|
</List>
|
||||||
|
</Section>
|
||||||
|
|
||||||
<Section>
|
<Section>
|
||||||
<Label>{ t('internship.sections.duration') }</Label>
|
<Label>{ t('internship.sections.duration') }</Label>
|
||||||
<Typography className="proposal__primary">
|
<Typography className="proposal__primary">
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import React, { HTMLProps, useEffect, useMemo, useState } from "react";
|
import React, { HTMLProps, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
Checkbox,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogContentText,
|
DialogContentText,
|
||||||
|
FormControlLabel,
|
||||||
|
FormGroup,
|
||||||
Grid,
|
Grid,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography
|
||||||
FormGroup,
|
|
||||||
FormControlLabel,
|
|
||||||
Checkbox
|
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import { KeyboardDatePicker as DatePicker } from "@material-ui/pickers";
|
import { KeyboardDatePicker as DatePicker } from "@material-ui/pickers";
|
||||||
import { CompanyForm } from "@/forms/company";
|
import { CompanyForm } from "@/forms/company";
|
||||||
@ -18,11 +18,11 @@ import { StudentForm } from "@/forms/student";
|
|||||||
import { sampleStudent } from "@/provider/dummy/student";
|
import { sampleStudent } from "@/provider/dummy/student";
|
||||||
import { Company, Internship, InternshipProgramEntry, InternshipType, Office, Student } from "@/data";
|
import { Company, Internship, InternshipProgramEntry, InternshipType, Office, Student } from "@/data";
|
||||||
import { Nullable } from "@/helpers";
|
import { Nullable } from "@/helpers";
|
||||||
import moment, { Moment } from "moment-timezone";
|
import { Moment } from "moment-timezone";
|
||||||
import { computeWorkingHours } from "@/utils/date";
|
import { computeWorkingHours } from "@/utils/date";
|
||||||
import { Autocomplete } from "@material-ui/lab";
|
import { Alert, AlertTitle, Autocomplete } from "@material-ui/lab";
|
||||||
import { emptyInternship } from "@/provider/dummy/internship";
|
import { emptyInternship } from "@/provider/dummy/internship";
|
||||||
import { useDispatch } from "@/state/actions";
|
import { InternshipProposalActions, useDispatch } from "@/state/actions";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { AppState } from "@/state/reducer";
|
import { AppState } from "@/state/reducer";
|
||||||
@ -38,7 +38,7 @@ import { useCurrentEdition, useCurrentStudent, useInternshipTypes, useUpdateEffe
|
|||||||
import { internshipRegistrationUpdateTransformer } from "@/api/dto/internship-registration";
|
import { internshipRegistrationUpdateTransformer } from "@/api/dto/internship-registration";
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
import FormLabel from "@material-ui/core/FormLabel";
|
import FormLabel from "@material-ui/core/FormLabel";
|
||||||
import { CheckBox } from "@material-ui/icons";
|
import { ValidationError, ValidationMessage } from "@/api/internship";
|
||||||
|
|
||||||
export type InternshipFormValues = {
|
export type InternshipFormValues = {
|
||||||
startDate: Moment | null;
|
startDate: Moment | null;
|
||||||
@ -145,7 +145,7 @@ const InternshipProgramForm = () => {
|
|||||||
{ possibleProgramEntries.map(
|
{ possibleProgramEntries.map(
|
||||||
entry => <FormControlLabel
|
entry => <FormControlLabel
|
||||||
control={ <Checkbox /> }
|
control={ <Checkbox /> }
|
||||||
checked={ selectedProgramEntries.includes(entry) }
|
checked={ selectedProgramEntries.find(cur => entry.id == cur.id) !== undefined }
|
||||||
onChange={ handleProgramEntryChange(entry) }
|
onChange={ handleProgramEntryChange(entry) }
|
||||||
label={ entry.description }
|
label={ entry.description }
|
||||||
key={ entry.id }
|
key={ entry.id }
|
||||||
@ -182,17 +182,21 @@ const InternshipDurationForm = () => {
|
|||||||
return (
|
return (
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item md={ 6 }>
|
<Grid item md={ 6 }>
|
||||||
<DatePicker value={ startDate } onChange={ value => setFieldValue("startDate", value) }
|
<DatePicker value={ startDate }
|
||||||
format="DD MMMM yyyy"
|
onChange={ value => setFieldValue("startDate", value) }
|
||||||
|
format="DD.MM.yyyy"
|
||||||
disableToolbar fullWidth
|
disableToolbar fullWidth
|
||||||
variant="inline" label={ t("forms.internship.fields.start-date") }
|
variant="inline"
|
||||||
|
label={ t("forms.internship.fields.start-date") }
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item md={ 6 }>
|
<Grid item md={ 6 }>
|
||||||
<DatePicker value={ endDate } onChange={ value => setFieldValue("endDate", value) }
|
<DatePicker value={ endDate }
|
||||||
format="DD MMMM yyyy"
|
onChange={ value => setFieldValue("endDate", value) }
|
||||||
|
format="DD.MM.yyyy"
|
||||||
disableToolbar fullWidth
|
disableToolbar fullWidth
|
||||||
variant="inline" label={ t("forms.internship.fields.end-date") }
|
variant="inline"
|
||||||
|
label={ t("forms.internship.fields.end-date") }
|
||||||
minDate={ startDate }
|
minDate={ startDate }
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -287,7 +291,12 @@ const converter: Transformer<Nullable<Internship>, InternshipFormValues, Interns
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const InternshipForm: React.FunctionComponent = () => {
|
export const InternshipForm: React.FunctionComponent = () => {
|
||||||
const student = useCurrentStudent();
|
const student = useCurrentStudent();
|
||||||
|
const history = useHistory();
|
||||||
|
const root = useRef<HTMLElement>(null);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const [errors, setErrors] = useState<ValidationMessage[]>([]);
|
||||||
|
|
||||||
const initialInternship = useSelector<AppState, Nullable<Internship>>(state => getInternshipProposal(state.proposal) || {
|
const initialInternship = useSelector<AppState, Nullable<Internship>>(state => getInternshipProposal(state.proposal) || {
|
||||||
...emptyInternship,
|
...emptyInternship,
|
||||||
@ -336,17 +345,25 @@ export const InternshipForm: React.FunctionComponent = () => {
|
|||||||
|
|
||||||
const values = converter.transform(initialInternship);
|
const values = converter.transform(initialInternship);
|
||||||
|
|
||||||
const handleSubmit = (values: InternshipFormValues) => {
|
const handleSubmit = async (values: InternshipFormValues) => {
|
||||||
setConfirmDialogOpen(false);
|
setConfirmDialogOpen(false);
|
||||||
|
|
||||||
const internship = converter.reverseTransform(values, { internship: initialInternship as Internship });
|
const internship = converter.reverseTransform(values, { internship: initialInternship as Internship });
|
||||||
const update = internshipRegistrationUpdateTransformer.transform(internship);
|
const update = internshipRegistrationUpdateTransformer.transform(internship);
|
||||||
|
|
||||||
console.log(update);
|
try {
|
||||||
|
await api.internship.update(update);
|
||||||
|
dispatch({ type: InternshipProposalActions.Send });
|
||||||
|
|
||||||
api.internship.update(update);
|
history.push(route("home"))
|
||||||
|
} catch (error) {
|
||||||
// history.push(route("home"))
|
if (error instanceof ValidationError) {
|
||||||
|
setErrors(error.messages);
|
||||||
|
root.current?.scrollIntoView({ behavior: "smooth" })
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnerForm = () => {
|
const InnerForm = () => {
|
||||||
@ -366,10 +383,16 @@ export const InternshipForm: React.FunctionComponent = () => {
|
|||||||
setConfirmDialogOpen(false);
|
setConfirmDialogOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Form>
|
return <Form ref={ root as any }>
|
||||||
|
{ errors.length > 0 && <Alert severity="warning">
|
||||||
|
<AlertTitle>{ t('internship.validation.has-errors') }</AlertTitle>
|
||||||
|
<ul style={{ paddingLeft: 0 }}>
|
||||||
|
{ errors.map(message => <li key={ message.key }>{ t(`internship.validation.${message.key}`, message.parameters) }</li>) }
|
||||||
|
</ul>
|
||||||
|
</Alert> }
|
||||||
<Typography variant="h3" className="section-header">{ t('internship.sections.intern-info') }</Typography>
|
<Typography variant="h3" className="section-header">{ t('internship.sections.intern-info') }</Typography>
|
||||||
<StudentForm />
|
<StudentForm />
|
||||||
<Typography variant="h3" className="section-header">{ t('internship.sections.kind' )}</Typography>
|
<Typography variant="h3" className="section-header">{ t('internship.sections.kind') }</Typography>
|
||||||
<InternshipProgramForm />
|
<InternshipProgramForm />
|
||||||
<Typography variant="h3" className="section-header">{ t('internship.sections.duration') }</Typography>
|
<Typography variant="h3" className="section-header">{ t('internship.sections.duration') }</Typography>
|
||||||
<InternshipDurationForm />
|
<InternshipDurationForm />
|
||||||
|
@ -5,6 +5,8 @@ import React, { useMemo } from "react";
|
|||||||
import { route } from "@/routing";
|
import { route } from "@/routing";
|
||||||
import { useAsync } from "@/hooks";
|
import { useAsync } from "@/hooks";
|
||||||
import api from "@/api";
|
import api from "@/api";
|
||||||
|
import { Loading } from "@/components/loading";
|
||||||
|
import { useSpacing } from "@/styles";
|
||||||
|
|
||||||
export const FallbackPage = () => {
|
export const FallbackPage = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@ -13,23 +15,23 @@ export const FallbackPage = () => {
|
|||||||
|
|
||||||
const { isLoading, value, error } = useAsync(promise);
|
const { isLoading, value, error } = useAsync(promise);
|
||||||
|
|
||||||
console.log({ isLoading, value, error, location });
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <CircularProgress />
|
return <div style={{ marginTop: "2rem" }}><Loading size="8rem"/></div>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <Page title="Strona nie została znaleziona">
|
return <Page title="Strona nie została znaleziona">
|
||||||
<Container>
|
<Container>
|
||||||
<Typography variant="h1">404</Typography>
|
<Box my={4}>
|
||||||
<Typography variant="h2">Strona nie została znaleziona</Typography>
|
<Typography variant="h1">404</Typography>
|
||||||
|
<Typography variant="h2">Strona nie została znaleziona</Typography>
|
||||||
|
|
||||||
<Box my={ 4 }>
|
<Box my={ 4 }>
|
||||||
<Divider variant="fullWidth"/>
|
<Divider variant="fullWidth"/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Button to={ route("home") } color="primary" component={ RouterLink }>strona główna</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Button to={ route("home") } color="primary" component={ RouterLink }>strona główna</Button>
|
|
||||||
</Container>
|
</Container>
|
||||||
</Page>
|
</Page>
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ export const InternshipProposalPreviewPage = () => {
|
|||||||
<DialogTitle>{ t("internship.accept.title") }</DialogTitle>
|
<DialogTitle>{ t("internship.accept.title") }</DialogTitle>
|
||||||
<DialogContent className={ classes.root }>
|
<DialogContent className={ classes.root }>
|
||||||
<Typography variant="body1">{ t("internship.accept.info") }</Typography>
|
<Typography variant="body1">{ t("internship.accept.info") }</Typography>
|
||||||
<TextField multiline value={ comment } onChange={ ev => setComment(ev.target.value) } fullWidth label={ t("comments") }/>
|
<TextField multiline value={ comment } onChange={ ev => setComment(ev.target.value) } fullWidth label={ t("comments") } rows={3}/>
|
||||||
|
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={ handleAcceptModalClose }>
|
<Button onClick={ handleAcceptModalClose }>
|
||||||
|
@ -17,7 +17,6 @@ export enum InternshipProposalActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SendProposalAction extends SendSubmissionAction<InternshipProposalActions.Send> {
|
export interface SendProposalAction extends SendSubmissionAction<InternshipProposalActions.Send> {
|
||||||
internship: Internship;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReceiveProposalApproveAction extends ReceiveSubmissionApproveAction<InternshipProposalActions.Approve> {
|
export interface ReceiveProposalApproveAction extends ReceiveSubmissionApproveAction<InternshipProposalActions.Approve> {
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
import { Reducer } from "react";
|
import { Reducer } from "react";
|
||||||
import { SubmissionAction } from "@/state/actions/submission";
|
import { SubmissionAction } from "@/state/actions/submission";
|
||||||
import { InternshipDocument, SubmissionState as ApiSubmissionState } from "@/api/dto/internship-registration";
|
import { InternshipDocument, SubmissionState as ApiSubmissionState } from "@/api/dto/internship-registration";
|
||||||
|
import { Api } from "mdi-material-ui";
|
||||||
|
|
||||||
export type InternshipPlanState = SubmissionState & MayRequireDeanApproval & {
|
export type InternshipPlanState = SubmissionState & MayRequireDeanApproval & {
|
||||||
document: Serializable<InternshipDocument> | null;
|
document: Serializable<InternshipDocument> | null;
|
||||||
@ -40,9 +41,14 @@ const internshipPlanReducer = (state: InternshipPlanState = defaultInternshipPla
|
|||||||
document: action.document,
|
document: action.document,
|
||||||
}
|
}
|
||||||
case InternshipPlanActions.Receive:
|
case InternshipPlanActions.Receive:
|
||||||
|
if (state.overwritten) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
accepted: action.state === ApiSubmissionState.Accepted,
|
accepted: action.state === ApiSubmissionState.Accepted,
|
||||||
|
declined: action.state === ApiSubmissionState.Rejected,
|
||||||
sent: [
|
sent: [
|
||||||
ApiSubmissionState.Accepted,
|
ApiSubmissionState.Accepted,
|
||||||
ApiSubmissionState.Rejected,
|
ApiSubmissionState.Rejected,
|
||||||
|
@ -42,12 +42,16 @@ const internshipProposalReducer = (state: InternshipProposalState = defaultInter
|
|||||||
case InternshipProposalActions.Send:
|
case InternshipProposalActions.Send:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
proposal: internshipSerializationTransformer.transform(action.internship),
|
|
||||||
}
|
}
|
||||||
case InternshipProposalActions.Receive:
|
case InternshipProposalActions.Receive:
|
||||||
|
if (state.overwritten) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
accepted: action.state === ApiSubmissionState.Accepted,
|
accepted: action.state === ApiSubmissionState.Accepted,
|
||||||
|
declined: action.state === ApiSubmissionState.Rejected,
|
||||||
sent: [
|
sent: [
|
||||||
ApiSubmissionState.Accepted,
|
ApiSubmissionState.Accepted,
|
||||||
ApiSubmissionState.Rejected,
|
ApiSubmissionState.Rejected,
|
||||||
|
@ -12,6 +12,7 @@ export type SubmissionState = {
|
|||||||
sentOn: string | null;
|
sentOn: string | null;
|
||||||
declined: boolean;
|
declined: boolean;
|
||||||
comment: string | null;
|
comment: string | null;
|
||||||
|
overwritten: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MayRequireDeanApproval = {
|
export type MayRequireDeanApproval = {
|
||||||
@ -24,6 +25,7 @@ export const defaultSubmissionState: SubmissionState = {
|
|||||||
sentOn: null,
|
sentOn: null,
|
||||||
declined: false,
|
declined: false,
|
||||||
comment: null,
|
comment: null,
|
||||||
|
overwritten: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultDeanApprovalsState: MayRequireDeanApproval = {
|
export const defaultDeanApprovalsState: MayRequireDeanApproval = {
|
||||||
@ -56,6 +58,7 @@ export function createSubmissionReducer<TState, TActionType, TAction extends Act
|
|||||||
accepted: true,
|
accepted: true,
|
||||||
declined: false,
|
declined: false,
|
||||||
comment: (action as ReceiveSubmissionApproveAction<any>).comment,
|
comment: (action as ReceiveSubmissionApproveAction<any>).comment,
|
||||||
|
overwritten: true,
|
||||||
}
|
}
|
||||||
case SubmissionAction.Decline:
|
case SubmissionAction.Decline:
|
||||||
return {
|
return {
|
||||||
@ -63,6 +66,7 @@ export function createSubmissionReducer<TState, TActionType, TAction extends Act
|
|||||||
accepted: false,
|
accepted: false,
|
||||||
declined: true,
|
declined: true,
|
||||||
comment: (action as ReceiveSubmissionDeclineAction<any>).comment,
|
comment: (action as ReceiveSubmissionDeclineAction<any>).comment,
|
||||||
|
overwritten: true,
|
||||||
}
|
}
|
||||||
case SubmissionAction.Send:
|
case SubmissionAction.Send:
|
||||||
return {
|
return {
|
||||||
@ -72,6 +76,7 @@ export function createSubmissionReducer<TState, TActionType, TAction extends Act
|
|||||||
accepted: false,
|
accepted: false,
|
||||||
declined: false,
|
declined: false,
|
||||||
comment: null,
|
comment: null,
|
||||||
|
overwritten: false,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -114,6 +114,11 @@ submission:
|
|||||||
draft: "wersja robocza"
|
draft: "wersja robocza"
|
||||||
|
|
||||||
internship:
|
internship:
|
||||||
|
validation:
|
||||||
|
has-errors: "W formularzu zostały znalezione błędy"
|
||||||
|
error:
|
||||||
|
declared_hours:
|
||||||
|
empty: "Brak zadeklarowanej długości praktyki."
|
||||||
intern:
|
intern:
|
||||||
semester: semestr {{ semester, roman }}
|
semester: semestr {{ semester, roman }}
|
||||||
album: "numer albumu {{ album }}"
|
album: "numer albumu {{ album }}"
|
||||||
@ -135,6 +140,7 @@ internship:
|
|||||||
place: "Miejsce odbywania praktyki"
|
place: "Miejsce odbywania praktyki"
|
||||||
kind: "Rodzaj i program praktyki"
|
kind: "Rodzaj i program praktyki"
|
||||||
mentor: "Zakładowy opiekun praktyki"
|
mentor: "Zakładowy opiekun praktyki"
|
||||||
|
program: "Realizowane punkty programu praktyki"
|
||||||
discard:
|
discard:
|
||||||
title: "Odrzuć zgłoszenie praktyki"
|
title: "Odrzuć zgłoszenie praktyki"
|
||||||
info: "Poniższa informacja zostanie przekazana praktykantowi w celu poprawy zgłoszenia."
|
info: "Poniższa informacja zostanie przekazana praktykantowi w celu poprawy zgłoszenia."
|
||||||
|
Loading…
Reference in New Issue
Block a user