diff --git a/src/management/common/LabelWithIcon.tsx b/src/management/common/LabelWithIcon.tsx
new file mode 100644
index 0000000..e1d2649
--- /dev/null
+++ b/src/management/common/LabelWithIcon.tsx
@@ -0,0 +1,28 @@
+import React from "react";
+import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
+
+const useStyles = makeStyles((theme: Theme) => createStyles({
+ root: {
+ display: "flex",
+ alignItems: "center"
+ },
+ icon: {
+ marginRight: theme.spacing(1),
+ display: "flex",
+ alignItems: "center"
+ }
+}))
+
+export type LabelWithIconProps = {
+ icon: React.ReactNode,
+ children: React.ReactChildren,
+}
+
+export function LabelWithIcon({ icon, children }: LabelWithIconProps) {
+ const classes = useStyles();
+
+ return
+
{ icon }
+ { children }
+
+}
diff --git a/src/management/type/edit.tsx b/src/management/type/edit.tsx
new file mode 100644
index 0000000..6b15745
--- /dev/null
+++ b/src/management/type/edit.tsx
@@ -0,0 +1,47 @@
+import { Button, Dialog, DialogActions, DialogContent, DialogProps, DialogTitle } from "@material-ui/core";
+import React from "react";
+import { Form, Formik } from "formik";
+import { initialStaticPageFormValues, StaticPageForm, StaticPageFormValues, staticPageFormValuesTransformer } from "@/management/page/form";
+import { Actions } from "@/components";
+import { Save } from "@material-ui/icons";
+import { useTranslation } from "react-i18next";
+import { Cancel } from "mdi-material-ui";
+import { useSpacing } from "@/styles";
+import { initialInternshipTypeFormValues, InternshipTypeForm, InternshipTypeFormValues, internshipTypeFormValuesTransformer } from "@/management/type/form";
+import { InternshipType } from "@/data";
+
+export type EditInternshipTypeDialogProps = {
+ onSave?: (page: InternshipType) => void;
+ value?: InternshipType;
+} & DialogProps;
+
+export function EditInternshipTypeDialog({ onSave, value, ...props }: EditInternshipTypeDialogProps) {
+ const { t } = useTranslation("management");
+ const spacing = useSpacing(3);
+
+ const handleSubmit = (values: InternshipTypeFormValues) => {
+ onSave?.(internshipTypeFormValuesTransformer.reverseTransform(values));
+ };
+
+ const initialValues = value
+ ? internshipTypeFormValuesTransformer.transform(value)
+ : initialInternshipTypeFormValues;
+
+ return
+}
+
diff --git a/src/management/type/form.tsx b/src/management/type/form.tsx
new file mode 100644
index 0000000..5b7a04c
--- /dev/null
+++ b/src/management/type/form.tsx
@@ -0,0 +1,55 @@
+import React from "react";
+import { InternshipType } from "@/data";
+import { useTranslation } from "react-i18next";
+import { useSpacing } from "@/styles";
+import { Field } from "formik";
+import { TextField as TextFieldFormik, Checkbox as CheckboxFormik } from "formik-material-ui";
+import { FormControlLabel, FormGroup, Typography } from "@material-ui/core";
+import { CKEditorField } from "@/field/ckeditor";
+import { AccountCheck, ShieldCheck } from "mdi-material-ui";
+import { identityTransformer, Transformer } from "@/serialization";
+import { LabelWithIcon } from "@/management/common/LabelWithIcon";
+
+export type InternshipTypeFormValues = Omit;
+
+export const initialInternshipTypeFormValues: InternshipTypeFormValues = {
+ label: {
+ pl: "",
+ en: "",
+ },
+ description: {
+ pl: "",
+ en: "",
+ },
+ requiresInsurance: false,
+ requiresDeanApproval: false,
+}
+
+export const internshipTypeFormValuesTransformer: Transformer = identityTransformer;
+
+export function InternshipTypeForm() {
+ const { t } = useTranslation("management");
+ const spacing = useSpacing(2);
+
+ return
+ { t("type.field.label") }
+
+
+ { t("type.field.description") }
+
+
+
+ { t("type.field.flags") }
+
+ }
+ label={ }>{ t("type.flag.dean-approval") } }
+ />
+ }
+ label={ }>{ t("type.flag.insurance") } }
+ />
+
+
+
+}
diff --git a/src/management/type/list.tsx b/src/management/type/list.tsx
index aad97a3..7d34c66 100644
--- a/src/management/type/list.tsx
+++ b/src/management/type/list.tsx
@@ -5,7 +5,7 @@ import { useAsyncState } from "@/hooks";
import { InternshipType } from "@/data";
import api from "@/management/api";
import { Management } from "@/management/main";
-import { Button, Container, Tooltip, Typography } from "@material-ui/core";
+import { Button, Container, IconButton, Tooltip, Typography } from "@material-ui/core";
import { Async } from "@/components/async";
import MaterialTable, { Column } from "material-table";
import { MaterialTableTitle } from "@/management/common/MaterialTableTitle";
@@ -17,6 +17,11 @@ import { BulkActions } from "@/management/common/BulkActions";
import { useSpacing } from "@/styles";
import { Actions } from "@/components";
import { MultilingualCell } from "@/management/common/MultilangualCell";
+import { default as StaticPage } from "@/data/page";
+import { Add, Edit } from "@material-ui/icons";
+import { createPortal } from "react-dom";
+import { EditStaticPageDialog } from "@/management/page/edit";
+import { EditInternshipTypeDialog } from "@/management/type/edit";
const title = "type.index.title";
@@ -41,6 +46,44 @@ export const InternshipTypeManagement = () => {
const DeleteTypeAction = createDeleteAction({ label, onDelete: handleTypeDelete });
+ const CreateTypeAction = () => {
+ const [ open, setOpen ] = useState(false);
+
+ const handleTypeCreation = async (value: InternshipType) => {
+ await api.type.save(value);
+ setOpen(false);
+ updateTypeList();
+ }
+
+ return <>
+ } onClick={ () => setOpen(true) }>{ t("create") }
+ { open && createPortal(
+ setOpen(false) }/>,
+ document.getElementById("modals") as Element
+ ) }
+ >
+ }
+
+ const EditTypeAction = ({ resource }: { resource: InternshipType }) => {
+ const [ open, setOpen ] = useState(false);
+
+ const handleTypeCreation = async (value: InternshipType) => {
+ await api.type.save(value);
+ setOpen(false);
+ updateTypeList();
+ }
+
+ return <>
+
+ setOpen(true) }>
+
+ { open && createPortal(
+ setOpen(false) }/>,
+ document.getElementById("modals") as Element
+ ) }
+ >
+ }
+
const columns: Column[] = [
{
field: "id",
@@ -61,16 +104,17 @@ export const InternshipTypeManagement = () => {
},
{
title: t("type.field.flags"),
- render: type => <>
+ render: type =>
{ type.requiresDeanApproval &&
}
{ type.requiresInsurance &&
}
- >,
+
,
width: 0,
filtering: true,
sorting: false,
},
actionsColumn(type => <>
+
>)
];
@@ -83,6 +127,7 @@ export const InternshipTypeManagement = () => {
+
}>{ t("refresh") }
{ selected.length > 0 &&
diff --git a/translations/management.pl.yaml b/translations/management.pl.yaml
index 02a238b..1367f4e 100644
--- a/translations/management.pl.yaml
+++ b/translations/management.pl.yaml
@@ -24,10 +24,14 @@ edition:
type:
index:
title: "Rodzeje praktyki"
+ edit:
+ title: "Edytuj rodzaj praktyki"
+ create:
+ title: "Utwórz rodzaj praktyki"
field:
label: "Rodzaj praktyki"
description: "Opis"
- flags: "Flagi"
+ flags: "Wymogi"
flag:
dean-approval: "Wymaga zgody dziekana"
insurance: "Wymaga ubezpieczenia"