164 lines
3.6 KiB
TypeScript
164 lines
3.6 KiB
TypeScript
import {
|
|
ApolloCache,
|
|
FetchResult,
|
|
gql,
|
|
Reference,
|
|
StoreObject,
|
|
} from "@apollo/client";
|
|
import {
|
|
FullAnswerFragment,
|
|
FullAnswerResponse,
|
|
QuestionAnswerResponse,
|
|
} from "../queries/answer";
|
|
import { CandidatePosition } from "../../components/CandidatePositionLegend";
|
|
|
|
export const EDIT_ANSWER = gql`
|
|
mutation UpdateAnswer($id: ID!, $position: Int, $text: String) {
|
|
updateAnswer(
|
|
input: { id: $id, answerPatch: { position: $position, text: $text } }
|
|
) {
|
|
answer {
|
|
...FullAnswerFragment
|
|
}
|
|
}
|
|
}
|
|
${FullAnswerFragment}
|
|
`;
|
|
|
|
export interface EditAnswerResponse {
|
|
updateAnswer: EditAnswerPayload | null;
|
|
}
|
|
|
|
export interface EditAnswerPayload {
|
|
answer: FullAnswerResponse;
|
|
__typename: "UpdateAnswerPayload";
|
|
}
|
|
|
|
export interface EditAnswerVariables {
|
|
id: string;
|
|
position?: CandidatePosition;
|
|
text?: string | null;
|
|
}
|
|
|
|
export const ADD_ANSWER = gql`
|
|
mutation AddAnswer(
|
|
$questionRowId: Int!
|
|
$personRowId: Int!
|
|
$position: Int!
|
|
$text: String
|
|
) {
|
|
createAnswer(
|
|
input: {
|
|
answer: {
|
|
questionRowId: $questionRowId
|
|
personRowId: $personRowId
|
|
position: $position
|
|
text: $text
|
|
}
|
|
}
|
|
) {
|
|
answer {
|
|
...FullAnswerFragment
|
|
}
|
|
}
|
|
}
|
|
${FullAnswerFragment}
|
|
`;
|
|
|
|
export interface AddAnswerResponse {
|
|
createAnswer: AddAnswerPayload | null;
|
|
}
|
|
|
|
export interface AddAnswerPayload {
|
|
answer: FullAnswerResponse;
|
|
__typename: "CreateAnswerPayload";
|
|
}
|
|
|
|
export interface AddAnswerVariables {
|
|
questionRowId: number;
|
|
personRowId: number;
|
|
position: CandidatePosition;
|
|
text?: string | null;
|
|
}
|
|
|
|
const matchesStoreFieldName = (
|
|
storeFieldName: string,
|
|
personRowId: number,
|
|
questionRowId: number
|
|
): boolean => {
|
|
const fullName = `answerByQuestionRowIdAndPersonRowId({"personRowId":${personRowId},"questionRowId":${questionRowId}})`;
|
|
return fullName === storeFieldName;
|
|
};
|
|
|
|
interface NodesCacheRefs {
|
|
nodes: Array<Reference | StoreObject>;
|
|
}
|
|
|
|
const addAnswerToQuestion = (
|
|
cache: ApolloCache<AddAnswerResponse>,
|
|
question: QuestionAnswerResponse,
|
|
newAnswerRef: Reference
|
|
) => {
|
|
cache.modify({
|
|
id: cache.identify({ ...question }),
|
|
fields: {
|
|
answersByQuestionRowId: (
|
|
answerRefs: NodesCacheRefs = { nodes: [] }
|
|
): NodesCacheRefs => {
|
|
return { nodes: [...answerRefs.nodes, newAnswerRef] };
|
|
},
|
|
},
|
|
});
|
|
};
|
|
|
|
const addAnswerToRootField = (
|
|
cache: ApolloCache<AddAnswerResponse>,
|
|
newAnswerRef: Reference,
|
|
personRowId: number,
|
|
questionRowId: number
|
|
) => {
|
|
cache.modify({
|
|
fields: {
|
|
answerByQuestionRowIdAndPersonRowId: (
|
|
answerRefs: Reference | StoreObject | null,
|
|
{ storeFieldName }
|
|
) => {
|
|
if (matchesStoreFieldName(storeFieldName, personRowId, questionRowId)) {
|
|
return newAnswerRef;
|
|
}
|
|
},
|
|
},
|
|
});
|
|
};
|
|
|
|
const writeAnswerToCache = (
|
|
cache: ApolloCache<AddAnswerResponse>,
|
|
answer: FullAnswerResponse
|
|
): Reference | undefined => {
|
|
return cache.writeFragment<FullAnswerResponse>({
|
|
data: answer,
|
|
fragment: FullAnswerFragment,
|
|
fragmentName: "FullAnswerFragment",
|
|
});
|
|
};
|
|
|
|
export const updateCacheAfterAddingAnswer = (
|
|
cache: ApolloCache<AddAnswerResponse>,
|
|
{ data }: FetchResult<AddAnswerResponse>,
|
|
question: QuestionAnswerResponse
|
|
): void => {
|
|
const answer = data?.createAnswer?.answer;
|
|
if (answer) {
|
|
const newAnswerRef = writeAnswerToCache(cache, answer);
|
|
if (newAnswerRef) {
|
|
addAnswerToQuestion(cache, question, newAnswerRef);
|
|
addAnswerToRootField(
|
|
cache,
|
|
newAnswerRef,
|
|
answer.personRowId,
|
|
answer.questionRowId
|
|
);
|
|
}
|
|
}
|
|
};
|