Skip to content

Commit

Permalink
refactor: contrib zod type (#1074)
Browse files Browse the repository at this point in the history
* refactor: make form specific types

* fix: updateDate

* chore: clean

* chore: clean

---------

Co-authored-by: Victor Zeinstra <[email protected]>
  • Loading branch information
Viczei and Victor Zeinstra authored Oct 9, 2023
1 parent f3bdf50 commit d250418
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Button, FormControl, Stack } from "@mui/material";
import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

import { FormEditionField, FormRadioGroup, FormTextField } from "../../forms";
import { Answer, Status, answerFormSchema } from "../type";
import { Answer, Status, answerRelationSchema, documentSchema } from "../type";
import { AnswerWithStatus } from "./answer.query";
import {
CdtnReferenceInput,
Expand All @@ -15,6 +16,55 @@ import {
import { getNextStatus, getPrimaryButtonLabel } from "../status/utils";
import { FicheSpDocumentInput } from "./references/FicheSpDocumentInput";

const answerFormBaseSchema = answerRelationSchema
.pick({
content: true,
contentType: true,
cdtnReferences: true,
kaliReferences: true,
legiReferences: true,
otherReferences: true,
contentFichesSpDocument: true,
})
.extend({
updateDate: z.string(),
});
const answerWithAnswerSchema = answerFormBaseSchema.extend({
contentType: z.literal("ANSWER"),
content: z
.string({
required_error: "Une réponse doit être renseigner",
invalid_type_error: "Une réponse doit être renseigner",
})
.min(1, "Une réponse doit être renseigner"),
});
const answerWithNothingSchema = answerFormBaseSchema.extend({
contentType: z.literal("NOTHING"),
});
const answerWithCdtSchema = answerFormBaseSchema.extend({
contentType: z.literal("CDT"),
});
const answerWithUnfavourableSchema = answerFormBaseSchema.extend({
contentType: z.literal("UNFAVOURABLE"),
});
const answerWithUnknownSchema = answerFormBaseSchema.extend({
contentType: z.literal("UNKNOWN"),
});
const answerWithSPSchema = answerFormBaseSchema.extend({
contentType: z.literal("SP"),
contentFichesSpDocument: documentSchema,
});

export const answerFormSchema = z.discriminatedUnion("contentType", [
answerWithAnswerSchema,
answerWithNothingSchema,
answerWithCdtSchema,
answerWithUnfavourableSchema,
answerWithUnknownSchema,
answerWithSPSchema,
]);
export type AnswerFormValidation = z.infer<typeof answerFormSchema>;

export type ContributionsAnswerProps = {
answer: AnswerWithStatus;
onSubmit: (status: Status, data: Answer) => void;
Expand All @@ -38,20 +88,18 @@ export const AnswerForm = ({
setStatus(answer.status.status);
}
}, [answer]);
const { control, getValues, trigger } = useForm<Answer>({
const { control, getValues, trigger } = useForm<AnswerFormValidation>({
resolver: zodResolver(answerFormSchema),
shouldFocusError: true,
defaultValues: {
content: "",
contentType: "ANSWER",
status: {
status: "TODO",
},
legiReferences: [],
kaliReferences: [],
otherReferences: [],
cdtnReferences: [],
contentFichesSpDocument: answer?.contentFichesSpDocument ? {} : undefined,
content: answer?.content ?? "",
contentType: answer?.contentType ?? "ANSWER",
legiReferences: answer?.legiReferences ?? [],
kaliReferences: answer?.kaliReferences ?? [],
otherReferences: answer?.otherReferences ?? [],
cdtnReferences: answer?.cdtnReferences ?? [],
contentFichesSpDocument: answer?.contentFichesSpDocument ?? undefined,
updateDate: answer?.updateDate ?? "",
},
});

Expand All @@ -60,8 +108,11 @@ export const AnswerForm = ({

if (isValid) {
setStatus(newStatus);
const data = getValues();
onSubmit(newStatus, data);
const formData = getValues();
onSubmit(newStatus, {
...answer,
...formData,
});
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@ type EditQuestionProps = {
messages: Message[];
};

const formDataSchema = questionRelationSchema.extend({
message_id: z
.string({
required_error: "Un message doit être sélectionné",
})
.uuid("Un message doit être sélectionné"),
const formDataSchema = questionRelationSchema.pick({
message_id: true,
content: true,
});
export type FormData = z.infer<typeof formDataSchema>;

Expand All @@ -32,7 +29,6 @@ export const EditQuestionForm = ({
shouldFocusError: true,
defaultValues: {
content: question.content,
id: question.id,
message_id: question.message?.id ?? "",
},
});
Expand All @@ -57,9 +53,9 @@ export const EditQuestionForm = ({
}
}, [watchMessageId, messages]);

const onSubmit = async (data: FormData) => {
const onSubmit = async (formData: FormData) => {
try {
const result = await updateQuestion(data);
const result = await updateQuestion({ id: question.id, ...formData });
if (result.error) {
setSnack({
message: `Erreur: ${result.error.message}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mutation contributionQuestionUpdate($id: uuid!, $content: String, $message_id: u
}
`;

type MutationProps = Question;
type MutationProps = Pick<Question, "id" | "content" | "message_id">;

type MutationResult = (props: MutationProps) => Promise<OperationResult>;

Expand Down
76 changes: 13 additions & 63 deletions targets/frontend/src/components/contributions/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,17 @@ export const cdtnReferenceSchema = z.object({
});
export type CdtnReference = z.infer<typeof cdtnReferenceSchema>;

export const contentTypeSchema = z.enum([
"ANSWER",
"NOTHING",
"CDT",
"UNFAVOURABLE",
"UNKNOWN",
"SP",
]);
export type ContentType = z.infer<typeof contentTypeSchema>;

const answerBaseSchema = z.object({
id: z.string().uuid(),
agreementId: z.string(),
questionId: z.string().uuid(),
contentType: z.string({
required_error: "Un type de réponse doit être sélectionner",
invalid_type_error: " type de réponse doit être sélectionner",
}),
contentType: z.enum(
["ANSWER", "NOTHING", "CDT", "UNFAVOURABLE", "UNKNOWN", "SP"],
{
required_error: "Un type de réponse doit être sélectionner",
invalid_type_error: " type de réponse doit être sélectionner",
}
),
contentServicePublicCdtnId: z.string().nullable().optional(),
content: z.string().nullable().optional(),
updatedAt: z.string(),
Expand All @@ -133,6 +126,11 @@ export const questionBaseSchema = z.object({
})
.min(1, "une question doit être renseigner"),
order: z.number(),
message_id: z
.string({
required_error: "Un message doit être sélectionné",
})
.uuid("Un message doit être sélectionné"),
});

export const commentsSchema = z.object({
Expand All @@ -146,7 +144,7 @@ export const commentsSchema = z.object({
});
export type Comments = z.infer<typeof commentsSchema>;

const answerRelationSchema = answerBaseSchema.extend({
export const answerRelationSchema = answerBaseSchema.extend({
agreement: agreementSchema,
statuses: z.array(answerStatusSchema),
status: answerStatusSchema,
Expand All @@ -160,56 +158,8 @@ const answerRelationSchema = answerBaseSchema.extend({
});
export type Answer = z.infer<typeof answerRelationSchema>;

export const answerFormBaseSchema = answerRelationSchema.extend({
id: z.string().uuid().optional(),
agreementId: z.string().optional(),
questionId: z.string().uuid().optional(),
updatedAt: z.string().optional(),
question: questionBaseSchema.deepPartial().optional(),
answerComments: z.array(commentsSchema.deepPartial()).optional(),
agreement: agreementSchema.deepPartial().optional(),
statuses: z.array(answerStatusSchema.deepPartial()).optional(),
status: answerStatusSchema.deepPartial().optional(),
});

export const questionRelationSchema = questionBaseSchema.extend({
answers: z.array(answerBaseSchema.deepPartial()).optional(),
message: messageSchema.deepPartial().optional(),
});
export type Question = z.infer<typeof questionRelationSchema>;

const answerWithAnswerSchema = answerFormBaseSchema.extend({
contentType: z.literal("ANSWER"),
content: z
.string({
required_error: "Une réponse doit être renseigner",
invalid_type_error: "Une réponse doit être renseigner",
})
.min(1, "Une réponse doit être renseigner"),
});
const answerWithNothingSchema = answerFormBaseSchema.extend({
contentType: z.literal("NOTHING"),
});
const answerWithCdtSchema = answerFormBaseSchema.extend({
contentType: z.literal("CDT"),
});
const answerWithUnfavourableSchema = answerFormBaseSchema.extend({
contentType: z.literal("UNFAVOURABLE"),
});
const answerWithUnknownSchema = answerFormBaseSchema.extend({
contentType: z.literal("UNKNOWN"),
});
const answerWithSPSchema = answerFormBaseSchema.extend({
contentType: z.literal("SP"),
contentFichesSpDocument: documentSchema,
});

export const answerFormSchema = z.discriminatedUnion("contentType", [
answerWithAnswerSchema,
answerWithNothingSchema,
answerWithCdtSchema,
answerWithUnfavourableSchema,
answerWithUnknownSchema,
answerWithSPSchema,
]);
export type AnswerForm = z.infer<typeof answerFormSchema>;

0 comments on commit d250418

Please sign in to comment.