#11 Add ChangeQuestionDialog w/o change functionality

This commit is contained in:
Christoph Lienhard 2020-12-28 15:56:29 +01:00
parent 524739cbbb
commit ea21617cf8
Signed by: christoph.lienhard
GPG key ID: 6B98870DDC270884
6 changed files with 210 additions and 20 deletions

View file

@ -14,11 +14,11 @@ export const allCategoriesQuery = gql`
export interface AllCategoriesQueryResponse {
allCategories: {
nodes: Array<AllCategoriesQueryNodes>
nodes: Array<GqlCategory>
}
}
interface AllCategoriesQueryNodes {
export interface GqlCategory {
nodeId: string,
title: string,
description: string,

View file

@ -8,6 +8,7 @@ export const allQuestionsQuery = gql`
text
description
categoryByCategoryId {
nodeId
title
}
}
@ -17,15 +18,18 @@ export const allQuestionsQuery = gql`
export interface AllQuestionsQueryResponse {
allQuestions: {
nodes: Array<AllQuestionsQueryNodes>
nodes: Array<GqlQuestion>
}
}
interface AllQuestionsQueryNodes {
export interface GqlQuestion {
nodeId: string,
text: string,
description: string,
categoryByCategoryId: {
title: string
}
categoryByCategoryId: AllQuestionsCategoryNode
}
interface AllQuestionsCategoryNode {
nodeId: string,
title: string,
}

View file

@ -36,6 +36,8 @@ interface QuestionProps {
title: string,
description: string,
subTitle?: string,
onEditButtonClick?(): void,
onDeleteButtonClick?(): void,
}
export default function AccordionWithEdit(props: QuestionProps) {
@ -63,10 +65,10 @@ export default function AccordionWithEdit(props: QuestionProps) {
</AccordionDetails>
<Divider/>
<AccordionActions>
<IconButton size={"small"} aria-label="edit">
<IconButton size={"small"} aria-label="edit" onClick={props.onEditButtonClick}>
<EditIcon/>
</IconButton>
<IconButton size={"small"} aria-label="delete">
<IconButton size={"small"} aria-label="delete" onClick={props.onDeleteButtonClick}>
<DeleteIcon/>
</IconButton>
</AccordionActions>

View file

@ -18,12 +18,16 @@ const useStyles = makeStyles((theme) => ({
},
}));
export default function AddCard() {
interface AddCardProps {
handleClick?(): void
}
export default function AddCard(props: AddCardProps) {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardActionArea>
<CardActionArea onClick={props.handleClick}>
<CardContent color={"textSecondary"} className={classes.addCardContent}>
<AddIcon className={classes.addCardIcon}/>
</CardContent>

View file

@ -0,0 +1,127 @@
import React, {ChangeEvent} from 'react';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import {makeStyles} from "@material-ui/core/styles";
import {FormControl, InputLabel, MenuItem, Select} from "@material-ui/core";
import {GqlCategory} from "../backend/queries/allCategories";
export interface ChangeQuestionDialogContent {
id: string
title: string,
details: string,
categoryId: string,
}
export const emptyChangeQuestionDialogContent: ChangeQuestionDialogContent = {
id: "",
title: "",
details: "",
categoryId: "",
}
interface ChangeQuestionDialogProps {
title: string,
confirmButtonText: string,
open: boolean,
categories?: Array<GqlCategory>,
content?: ChangeQuestionDialogContent,
handleContentChange?(content: ChangeQuestionDialogContent): void
handleConfirmButtonClick(): void,
handleClose(): void,
}
const useStyles = makeStyles((theme) => ({
textField: {
marginBottom: theme.spacing(2),
},
formControl: {},
}));
export default function ChangeQuestionDialog(props: ChangeQuestionDialogProps) {
const classes = useStyles();
const content = props.content ? props.content : emptyChangeQuestionDialogContent;
const onTitleChange = (e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
const newValue = e.target.value;
props.handleContentChange?.({
...content,
title: newValue,
});
}
const onDetailsChange = (e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
const newValue = e.target.value;
props.handleContentChange?.({
...content,
details: newValue,
});
}
const onCategoryIdChange = (e: ChangeEvent<{ name?: string, value: unknown }>) => {
const newValue = e.target.value as string;
props.handleContentChange?.({
...content,
categoryId: newValue,
});
}
return (
<Dialog open={props.open} onClose={props.handleClose} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">{props.title}</DialogTitle>
<DialogContent>
<TextField
className={classes.textField}
id="title"
label="Zusammenfassung"
fullWidth
variant="outlined"
value={content.title}
onChange={onTitleChange}
/>
<TextField
className={classes.textField}
multiline
rows={4}
id="description"
label="Details"
fullWidth
variant="outlined"
value={content.details}
onChange={onDetailsChange}
/>
<FormControl fullWidth variant="outlined" className={classes.formControl}>
<InputLabel>Kategorie</InputLabel>
<Select
value={content.categoryId}
label="Kategorie"
onChange={onCategoryIdChange}
>
<MenuItem value={undefined}>
<em>None</em>
</MenuItem>
{props.categories?.map(category => <MenuItem key={category.nodeId} value={category.nodeId}>
{category.title}
</MenuItem>)}
</Select>
</FormControl>
</DialogContent>
<DialogActions>
<Button onClick={props.handleClose} color="primary">
Abbrechen
</Button>
<Button onClick={props.handleConfirmButtonClick} color="primary">
{props.confirmButtonText}
</Button>
</DialogActions>
</Dialog>
);
}

View file

@ -1,10 +1,15 @@
import {Paper, Typography} from "@material-ui/core";
import React from "react";
import React, {useState} from "react";
import {makeStyles} from "@material-ui/core/styles";
import {useQuery} from "@apollo/client";
import AddCard from "./AddCard";
import AccordionWithEdit from "./AccordionWithEdit";
import {allQuestionsQuery, AllQuestionsQueryResponse} from "../backend/queries/allQuestions";
import {allQuestionsQuery, AllQuestionsQueryResponse, GqlQuestion} from "../backend/queries/allQuestions";
import ChangeQuestionDialog, {
ChangeQuestionDialogContent,
emptyChangeQuestionDialogContent
} from "./ChangeQuestionDialog";
import {allCategoriesQuery, AllCategoriesQueryResponse} from "../backend/queries/allCategories";
const useStyles = makeStyles((theme) => ({
root: {
@ -15,19 +20,67 @@ const useStyles = makeStyles((theme) => ({
}));
export default function QuestionList() {
const {data} = useQuery<AllQuestionsQueryResponse, null>(allQuestionsQuery);
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogTitle, setDialogTitle] = useState("");
const [dialogConfirmButtonText, setDialogConfirmButtonText] = useState("");
const [dialogContent, setDialogContent] = useState(emptyChangeQuestionDialogContent);
const questions = useQuery<AllQuestionsQueryResponse, null>(allQuestionsQuery).data?.allQuestions.nodes;
const categories = useQuery<AllCategoriesQueryResponse, null>(allCategoriesQuery).data?.allCategories.nodes;
const classes = useStyles();
const handleAddClick = () => {
setDialogTitle("Neue Frage erstellen");
setDialogConfirmButtonText("Erstellen");
if (dialogContent.id !== "") {
setDialogContent(emptyChangeQuestionDialogContent);
}
setDialogOpen(true);
}
const handleEditButtonClick = (question: GqlQuestion) => {
setDialogTitle("Frage bearbeiten");
setDialogConfirmButtonText("Speichern")
if (dialogContent.id !== question.nodeId) {
setDialogContent({
id: question.nodeId,
title: question.text,
details: question.description,
categoryId: question.categoryByCategoryId.nodeId,
})
}
setDialogOpen(true);
};
const handleDialogContentChange = (content: ChangeQuestionDialogContent) => {
setDialogContent(content)
}
return (
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>Fragen</Typography>
{data?.allQuestions.nodes.map(question => <AccordionWithEdit
key={question.nodeId}
title={question.text}
subTitle={question.categoryByCategoryId.title}
description={question.description}/>
{questions?.map(question => {
return <AccordionWithEdit
key={question.nodeId}
title={question.text}
subTitle={question.categoryByCategoryId.title}
description={question.description}
onEditButtonClick={() => handleEditButtonClick(question)}
/>;
}
)}
<AddCard/>
<AddCard handleClick={handleAddClick}/>
<ChangeQuestionDialog
title={dialogTitle}
confirmButtonText={dialogConfirmButtonText}
open={dialogOpen}
content={dialogContent}
categories={categories}
handleContentChange={handleDialogContentChange}
handleConfirmButtonClick={() => {
console.log("go for question mutation");
setDialogOpen(false);
}}
handleClose={() => setDialogOpen(false)}/>
</Paper>
)
}