Skip to content

Commit

Permalink
Add edit and delete answers
Browse files Browse the repository at this point in the history
  • Loading branch information
maxidragon committed Sep 21, 2023
1 parent 273b630 commit 7b931bf
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 30 deletions.
27 changes: 20 additions & 7 deletions backend/app/controllers/answers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,32 @@ def create

def update
answer = Answer.find(params[:id])
authorize_answer
if answer.update(answer_params)
render json: answer
if answer.present? && answer.question.quiz.user == current_user
answer_params = params.require(:answer).permit(:text, :is_correct)
if answer.update(answer_params)
render json: {
answer: answer,
status: :updated
}
else
render json: {error: answer.errors.full_messages}, status: :unprocessable_entity
end
else
render json: {error: answer.errors.full_messages}, status: :unprocessable_entity
render json: {error: "Answer not found"}, status: :not_found
end
end

def destroy
answer = Answer.find(params[:id])
authorize_answer
answer.destroy
render json: answer
if answer.present? && answer.question.quiz.user == current_user
answer.destroy
render json: {
answer: answer,
status: :deleted
}
else
render json: {error: "Answer not found"}, status: :not_found
end
end

end
83 changes: 83 additions & 0 deletions frontend/src/Components/ModalComponents/Edit/EditAnswerModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
Box,
Typography,
Modal,
TextField,
Grid,
Checkbox,
FormControlLabel,
} from "@mui/material";
import { formStyle, style } from "../modalStyles";
import { enqueueSnackbar } from "notistack";
import ActionsButtons from "../ActionsButtons";
import EditIcon from "@mui/icons-material/Edit";
import { editAnswer } from "../../../logic/answers";
import { Answer } from "../../../logic/interfaces";

const EditAnswerModal = (props: {
open: boolean;
handleClose: () => void;
answer: Answer;
quizId: number;
updateAnswer: (answer: Answer) => void;
}) => {
const handleEdit = async () => {
const response = await editAnswer(props.answer, props.quizId);
if (response.status === "updated") {
enqueueSnackbar("Answer updated!", { variant: "success" });
props.handleClose();
} else {
enqueueSnackbar("Something went wrong!", { variant: "error" });
}
};
return (
<Modal open={props.open} onClose={props.handleClose}>
<Box sx={style}>
<Grid container sx={formStyle}>
<Grid item>
<Typography id="modal-modal-title" variant="h6" component="h2">
Edit answer
</Typography>
</Grid>
<Grid item>
<TextField
placeholder={"Text"}
fullWidth
value={props.answer.text}
onChange={(event) =>
props.updateAnswer({
...props.answer,
text: event.target.value,
})
}
/>
</Grid>
<Grid item>
<FormControlLabel
control={
<Checkbox
checked={props.answer.is_correct}
onChange={(event) =>
props.updateAnswer({
...props.answer,
is_correct: event.target.checked,
})
}
/>
}
label="Correct"
/>
</Grid>
</Grid>
<ActionsButtons
cancel={props.handleClose}
submit={handleEdit}
submitText={"Edit"}
submitIcon={<EditIcon />}
/>
</Box>
</Modal>
);
};

export default EditAnswerModal;
93 changes: 93 additions & 0 deletions frontend/src/Components/Questions/AnswerRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useState } from "react";
import { TableRow, TableCell, IconButton } from "@mui/material";
import { Answer } from "../../logic/interfaces";
import { useConfirm } from "material-ui-confirm";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
import EditAnswerModal from "../ModalComponents/Edit/EditAnswerModal";
import { enqueueSnackbar } from "notistack";
import { deleteAnswer } from "../../logic/answers";

const AnswerRow = (props: {
answerRow: Answer;
answerNumber: number;
quizId: number;
}) => {
const confirm = useConfirm();
const { answerRow } = props;
const [hide, setHide] = useState<boolean>(false);
const [editedAnswer, setEditedAnswer] = useState<Answer>(answerRow);
const [openEditAnswerModal, setOpenEditAnswerModal] =
useState<boolean>(false);

const handleDelete = async () => {
if (answerRow === null) return;
confirm({
description: "Are you sure you want to delete this answer?",
})
.then(async () => {
const response = await deleteAnswer(
props.quizId,
answerRow.question_id,
answerRow.id,
);
if (response.status === "deleted") {
enqueueSnackbar("Answer deleted!", { variant: "success" });
setHide(true);
} else {
enqueueSnackbar("Something went wrong!", { variant: "error" });
}
})
.catch(() => {
enqueueSnackbar("Answer not deleted!", { variant: "info" });
});
};

const updateAnswer = (answer: Answer) => {
setEditedAnswer(answer);
};

return (
<>
{!hide && (
<>
<TableRow key={answerRow.id}>
<TableCell
sx={{
width: "10px",
}}
>
{props.answerNumber + 1}
</TableCell>
<TableCell component="th" scope="row">
{answerRow.text}
</TableCell>
<TableCell>{answerRow.is_correct ? "Yes" : "No"}</TableCell>
<TableCell>
<IconButton
onClick={() => {
setOpenEditAnswerModal(true);
}}
>
<EditIcon />
</IconButton>
<IconButton onClick={handleDelete}>
<DeleteIcon />
</IconButton>
</TableCell>
</TableRow>

<EditAnswerModal
open={openEditAnswerModal}
handleClose={() => setOpenEditAnswerModal(false)}
answer={editedAnswer}
quizId={props.quizId}
updateAnswer={updateAnswer}
/>
</>
)}
</>
);
};

export default AnswerRow;
24 changes: 8 additions & 16 deletions frontend/src/Components/Questions/QuestionRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import AddIcon from "@mui/icons-material/Add";
import EditQuestionModal from "../ModalComponents/Edit/EditQuestionModal";
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";
import AnswerRow from "./AnswerRow";

const QuestionRow = (props: {
row: Question;
Expand All @@ -31,7 +32,7 @@ const QuestionRow = (props: {
const confirm = useConfirm();
const { row } = props;
const [hide, setHide] = useState<boolean>(false);
const [editedQuestion, setEditedQuestion] = useState<Question>(props.row);
const [editedQuestion, setEditedQuestion] = useState<Question>(row);
const [open, setOpen] = useState(false);
const [openCreateModal, setOpenCreateModal] = useState<boolean>(false);
const [openEditQuestionModal, setOpenEditQuestionModal] =
Expand Down Expand Up @@ -137,21 +138,12 @@ const QuestionRow = (props: {
</TableHead>
<TableBody>
{row.answers.map((answerRow, answerNumber: number) => (
<TableRow key={answerRow.id}>
<TableCell
sx={{
width: "10px",
}}
>
{answerNumber + 1}
</TableCell>
<TableCell component="th" scope="row">
{answerRow.text}
</TableCell>
<TableCell>
{answerRow.is_correct ? "Yes" : "No"}
</TableCell>
</TableRow>
<AnswerRow
key={answerRow.id}
answerRow={answerRow}
quizId={row.quiz_id}
answerNumber={answerNumber}
/>
))}
</TableBody>
</Table>
Expand Down
26 changes: 19 additions & 7 deletions frontend/src/logic/answers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Answer } from "./interfaces";
import { backendRequest } from "./request";

export const createAnswer = async (
Expand All @@ -19,19 +20,30 @@ export const createAnswer = async (
}
};

export const editAnswer = async (
quizId: number,
export const editAnswer = async (answer: Answer, quizId: number) => {
try {
const response = await backendRequest(
`/quizzes/${quizId}/questions/${answer.question_id}/answers/${answer.id}`,
"PUT",
true,
answer,
);
return await response.json();
} catch (error) {
console.log(error);
}
};

export const deleteAnswer = async (
quiz_id: number,
question_id: number,
answer_id: number,
text: string,
is_correct: boolean,
) => {
try {
const response = await backendRequest(
`/quizzes/${quizId}/questions/${question_id}/answers/${answer_id}`,
"PUT",
`/quizzes/${quiz_id}/questions/${question_id}/answers/${answer_id}`,
"DELETE",
true,
{ text, is_correct, question_id },
);
return await response.json();
} catch (error) {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/logic/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface Answer {
id: number;
text: string;
is_correct: boolean;
question_id: number;
}

export interface User {
Expand Down

0 comments on commit 7b931bf

Please sign in to comment.