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 + +
+ { t(value ? "type.edit.title" : "type.create.title") } + + + + + + + + + +
+
+
+} + 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 <> + + { 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 = () => { + { 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"