160 lines
4.7 KiB
TypeScript
160 lines
4.7 KiB
TypeScript
import React from "react";
|
|
import { CandidatePosition } from "./CandidatePositionLegend";
|
|
import { useMutation, useQuery } from "@apollo/client";
|
|
import {
|
|
FullAnswerResponse,
|
|
GET_ANSWER_BY_QUESTION_AND_PERSON,
|
|
GetAnswerByQuestionAndPersonResponse,
|
|
GetAnswerByQuestionAndPersonVariables,
|
|
QuestionAnswerResponse,
|
|
} from "../backend/queries/answer";
|
|
import { useSnackbar } from "notistack";
|
|
import {
|
|
ADD_ANSWER,
|
|
AddAnswerResponse,
|
|
AddAnswerVariables,
|
|
EDIT_ANSWER,
|
|
EditAnswerResponse,
|
|
EditAnswerVariables,
|
|
updateCacheAfterAddingAnswer,
|
|
} from "../backend/mutations/answer";
|
|
import ToggleButtonGroupAnswerPosition from "./ToggleButtonGroupAnswerPosition";
|
|
import EditAnswerText from "./EditAnswerText";
|
|
|
|
interface EditAnswerSectionProps {
|
|
loggedInPersonRowId: number;
|
|
question: QuestionAnswerResponse;
|
|
}
|
|
|
|
export default function EditAnswerSection(
|
|
props: EditAnswerSectionProps
|
|
): React.ReactElement {
|
|
const { enqueueSnackbar } = useSnackbar();
|
|
const { data } = useQuery<
|
|
GetAnswerByQuestionAndPersonResponse,
|
|
GetAnswerByQuestionAndPersonVariables
|
|
>(GET_ANSWER_BY_QUESTION_AND_PERSON, {
|
|
variables: {
|
|
personRowId: props.loggedInPersonRowId,
|
|
questionRowId: props.question.rowId,
|
|
},
|
|
});
|
|
const remoteAnswer = data?.answerByQuestionRowIdAndPersonRowId;
|
|
const [editAnswer, { loading: editAnswerLoading }] = useMutation<
|
|
EditAnswerResponse,
|
|
EditAnswerVariables
|
|
>(EDIT_ANSWER, {
|
|
onError: (e) =>
|
|
enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, {
|
|
variant: "error",
|
|
}),
|
|
});
|
|
const [addAnswer, { loading: addAnswerLoading }] = useMutation<
|
|
AddAnswerResponse,
|
|
AddAnswerVariables
|
|
>(ADD_ANSWER, {
|
|
onError: (e) =>
|
|
enqueueSnackbar(`Ein Fehler ist aufgetreten: ${e.message}`, {
|
|
variant: "error",
|
|
}),
|
|
update: (cache, fetchResult) =>
|
|
updateCacheAfterAddingAnswer(cache, fetchResult, props.question),
|
|
});
|
|
|
|
const parsePosition = (position?: CandidatePosition): CandidatePosition => {
|
|
return position !== undefined ? position : CandidatePosition.skipped;
|
|
};
|
|
const changeAnswer = async (
|
|
position?: CandidatePosition,
|
|
text?: string
|
|
): Promise<FullAnswerResponse | undefined> => {
|
|
if (remoteAnswer) {
|
|
const optimisticResponseAnswer = {
|
|
...remoteAnswer,
|
|
...(position !== undefined && { position }),
|
|
...(text !== undefined && { text }),
|
|
};
|
|
const response = await editAnswer({
|
|
variables: {
|
|
id: remoteAnswer.id,
|
|
position,
|
|
text,
|
|
},
|
|
optimisticResponse: {
|
|
updateAnswer: {
|
|
__typename: "UpdateAnswerPayload",
|
|
answer: optimisticResponseAnswer,
|
|
},
|
|
},
|
|
});
|
|
return response.data?.updateAnswer?.answer;
|
|
} else {
|
|
const savePosition = parsePosition(position);
|
|
const response = await addAnswer({
|
|
variables: {
|
|
personRowId: props.loggedInPersonRowId,
|
|
questionRowId: props.question.rowId,
|
|
position: savePosition,
|
|
text: text,
|
|
},
|
|
optimisticResponse: {
|
|
createAnswer: {
|
|
__typename: "CreateAnswerPayload",
|
|
answer: {
|
|
id: "somethingIntermediate",
|
|
position: savePosition,
|
|
text: text || null,
|
|
personRowId: props.loggedInPersonRowId,
|
|
questionRowId: props.question.rowId,
|
|
__typename: "Answer",
|
|
},
|
|
},
|
|
},
|
|
});
|
|
return response.data?.createAnswer?.answer;
|
|
}
|
|
};
|
|
const handleSaveText = async (text: string) => {
|
|
const newAnswer = await changeAnswer(undefined, text);
|
|
if (newAnswer) {
|
|
enqueueSnackbar("Antwort erfolgreich gespeichert.", {
|
|
variant: "success",
|
|
});
|
|
} else {
|
|
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", {
|
|
variant: "error",
|
|
});
|
|
}
|
|
};
|
|
const handlePositionChange = async (
|
|
e: React.MouseEvent<HTMLElement>,
|
|
newPosition: CandidatePosition
|
|
) => {
|
|
const newAnswer = await changeAnswer(newPosition);
|
|
if (!newAnswer) {
|
|
enqueueSnackbar("Ein Fehler ist aufgetreten, versuche es erneut.", {
|
|
variant: "error",
|
|
});
|
|
}
|
|
};
|
|
const loading = editAnswerLoading || addAnswerLoading;
|
|
const position = parsePosition(remoteAnswer?.position);
|
|
|
|
return remoteAnswer === undefined ? (
|
|
<div>Antwort laden...</div>
|
|
) : (
|
|
<React.Fragment>
|
|
<ToggleButtonGroupAnswerPosition
|
|
position={position}
|
|
onPositionChange={handlePositionChange}
|
|
loading={loading}
|
|
/>
|
|
<EditAnswerText
|
|
remoteText={remoteAnswer?.text}
|
|
onSaveClick={handleSaveText}
|
|
loading={loading}
|
|
/>
|
|
</React.Fragment>
|
|
);
|
|
}
|