feat: 설문 결과 페이지 추가 작업

This commit is contained in:
2025-06-10 17:37:57 +09:00
parent d86f56ed7e
commit e9e0a574da
7 changed files with 36 additions and 28 deletions
@@ -12,7 +12,7 @@ import { ArticleManagementDialog } from "../ui/article-management-dialog";
const QUESTION_TYPE = {
RADIO: "객관식",
CHECK: "다중응답",
CHECKBOX: "다중응답",
INPUT: "주관식",
} as const;
@@ -3,7 +3,7 @@ import type { PageableList, PageableParams } from "@/shared/model";
export const QUESTION_TYPE_CODE = {
RADIO: "RADIO",
CHECK: "CHECK",
CHECKBOX: "CHECKBOX",
INPUT: "INPUT",
} as const;
@@ -1,3 +1,4 @@
import { useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useQueryClient } from "@tanstack/react-query";
@@ -11,6 +12,7 @@ import {
DialogTitle,
DialogTrigger,
} from "@common/components";
import { ENDPOINT } from "@/shared/config";
import { useAlertStore, useMutationWrapper } from "@/shared/lib";
import {
questionFormSchema,
@@ -18,7 +20,6 @@ import {
} from "../model/survey-interface";
import { QuestionForm } from "./question-form";
import { SurveyApi } from "../api/survey-service";
import { ENDPOINT } from "@/shared/config";
type QuestionAddDialogProps = {
srvySn: number;
@@ -46,11 +47,16 @@ function QuestionAddDialog({
onOpenChange?.(false);
},
});
const form = useForm<QuestionFormData>({
resolver: zodResolver(questionFormSchema),
defaultValues: { maxChcCnt: 0, etcAnsYn: "N" },
});
useEffect(() => {
if (!open) form.reset({ maxChcCnt: 0, etcAnsYn: "N" });
}, [open]);
return (
<Dialog open={open} onOpenChange={onOpenChange} {...props}>
<DialogTrigger asChild>
@@ -76,7 +76,7 @@ function QuestionForm({ form, actionSlot, handleSave }: QuestionFormProps) {
<FormControl>
<CodeSelect
{...field}
upCd="SRVYTYPE"
upCd="SRVYQSTN"
value={field.value ?? ""}
onValueChange={field.onChange}
/>
@@ -107,7 +107,7 @@ function QuestionForm({ form, actionSlot, handleSave }: QuestionFormProps) {
/>
</TableCell>
</TableRow>
{qstnTypeCd === "CHECK" && (
{qstnTypeCd === "CHECKBOX" && (
<TableRow>
<TableHead>최대선택갯수</TableHead>
<TableCell className="border">
@@ -134,7 +134,7 @@ function QuestionForm({ form, actionSlot, handleSave }: QuestionFormProps) {
</TableCell>
</TableRow>
)}
{(qstnTypeCd === "RADIO" || qstnTypeCd === "CHECK") && (
{(qstnTypeCd === "RADIO" || qstnTypeCd === "CHECKBOX") && (
<TableRow>
<TableHead>기타답변여부</TableHead>
<TableCell className="border">
@@ -210,7 +210,7 @@ function UserSurveyArticle({ srvySn }: { srvySn: string }) {
articles={item.articles}
/>
)}
{item.qstnTypeCd === "CHECK" && (
{item.qstnTypeCd === "CHECKBOX" && (
<CheckArticle
form={form}
qstnCn={item.qstnCn}
@@ -31,7 +31,7 @@ import {
CategoryScale,
LinearScale,
BarElement,
type PluginChartOptions,
type ChartOptions,
} from "chart.js";
import { Pie, Bar } from "react-chartjs-2";
@@ -144,7 +144,7 @@ function UserSurveyResult({ srvySn }: { srvySn: string }) {
{item.qstnTypeCd === "RADIO" && (
<WithPieChartResult data={item} index={index} />
)}
{item.qstnTypeCd === "CHECK" && (
{item.qstnTypeCd === "CHECKBOX" && (
<WithBarChartResult data={item} index={index} />
)}
{item.qstnTypeCd === "INPUT" && (
@@ -181,7 +181,7 @@ function WithPieChartResult({
},
],
};
const options = {
const options: ChartOptions<"pie"> = {
plugins: {
legend: {
position: "right",
@@ -197,12 +197,9 @@ function WithPieChartResult({
</span>
<span className="font-medium text-foreground">{data?.qstnCn}</span>
</h2>
<div className="flex gap-4">
<div className="flex gap-8">
<div className="h-[28rem] w-[28rem] shrink-0">
<Pie
data={chartData}
options={options as PluginChartOptions<"pie">}
/>
<Pie data={chartData} options={options} />
</div>
<Table variant="secondary" className="text-center">
<TableHeader>
@@ -247,12 +244,19 @@ function WithBarChartResult({
},
],
};
const options = {
const options: ChartOptions<"bar"> = {
plugins: {
legend: {
position: "bottom",
},
},
layout: {
padding: {
top: 40,
bottom: 20,
},
},
maintainAspectRatio: false,
};
return (
@@ -263,12 +267,9 @@ function WithBarChartResult({
</span>
<span className="font-medium text-foreground">{data?.qstnCn}</span>
</h2>
<div className="flex gap-4">
<div className="flex gap-8">
<div className="h-[28rem] w-[28rem] shrink-0">
<Bar
data={chartData}
options={options as PluginChartOptions<"bar">}
/>
<Bar data={chartData} options={options} />
</div>
<Table variant="secondary" className="text-center">
<TableHeader>
@@ -301,7 +302,7 @@ function InputResult({
index: number;
}) {
return (
<>
<div className="my-10">
<h2 className="flex items-center gap-2">
<span className="flex size-8 items-center justify-center rounded-full bg-primary text-[1.3rem] font-medium text-primary-foreground">
{index + 1}
@@ -328,7 +329,7 @@ function InputResult({
</div>
))}
</div>
</>
</div>
);
}
@@ -17,11 +17,12 @@ export const useMutationWrapper = <
let errorMessage = "";
if (error instanceof AxiosError) {
if (error.response?.status) errorMessage += `status: ${error.status}\n`;
if (error.response?.data.message)
errorMessage += `${error.response?.data.message}\n`;
if (error.response?.data.errors[0].message)
errorMessage += `${error.response?.data.errors[0].message}\n`;
if (error.response?.status)
errorMessage += `status: ${error.response.status}\n`;
if (error.response?.data?.message)
errorMessage += `${error.response.data.message}\n`;
if (error.response?.data?.errors[0]?.message)
errorMessage += `${error.response.data.errors[0].message}\n`;
}
alert(`[Error] ${errorMessage}`);