diff --git a/src/app/(authed)/admin/answer/[answerId]/_components/AnswerDetails.tsx b/src/app/(authed)/admin/answer/[answerId]/_components/AnswerDetails.tsx index fb4f5b66..5e5cf188 100644 --- a/src/app/(authed)/admin/answer/[answerId]/_components/AnswerDetails.tsx +++ b/src/app/(authed)/admin/answer/[answerId]/_components/AnswerDetails.tsx @@ -10,9 +10,13 @@ import { useForm } from 'react-hook-form'; import { removeDuplicates } from '@/generic/ArrayExtra'; import { formatString } from '@/generic/DateFormatter'; import type { + GetAnswerLabelsResponse, GetAnswerResponse, GetQuestionsResponse, } from '@/app/api/_schemas/ResponseSchemas'; +import Autocomplete from '@mui/material/Autocomplete'; +import Chip from '@mui/material/Chip'; +import Box from '@mui/material/Box'; const AnswerTitleForm = (props: { answers: GetAnswerResponse }) => { const { handleSubmit, register } = useForm<{ title: string }>(); @@ -70,7 +74,48 @@ const AnswerTitleForm = (props: { answers: GetAnswerResponse }) => { ); }; -const AnswerMeta = (props: { answers: GetAnswerResponse }) => { +const AnswerTags = (props: { labels: GetAnswerLabelsResponse }) => { + return ( + label.name)} + getOptionLabel={(option) => option} + defaultValue={[]} + renderTags={(value: readonly string[], getTagProps) => + value.map((option: string, index: number) => ( + + )) + } + renderOption={(props, option) => { + return ( + + {option} + + ); + }} + renderInput={(params) => ( + // @ts-expect-error (解決方法がよくわからないのでとりあえずignoreする) + // FIXME: あとで調べる + + )} + /> + ); +}; + +const AnswerMeta = (props: { + answers: GetAnswerResponse; + labels: GetAnswerLabelsResponse; +}) => { return ( @@ -81,6 +126,10 @@ const AnswerMeta = (props: { answers: GetAnswerResponse }) => { 回答日時 {formatString(props.answers.timestamp)} + + ラベル + + ); }; @@ -104,6 +153,7 @@ const Answers = (props: { answers: AnswerWithQuestionInfo }) => { const AnswerDetails = (props: { answers: GetAnswerResponse; questions: GetQuestionsResponse; + labels: GetAnswerLabelsResponse; }) => { const answerWithQeustionInfo = removeDuplicates( props.answers.answers.map((answer) => answer.question_id) @@ -123,7 +173,7 @@ const AnswerDetails = (props: { return ( - + {answerWithQeustionInfo.length === 0 ? ( 回答がありません ) : ( diff --git a/src/app/(authed)/admin/answer/[answerId]/page.tsx b/src/app/(authed)/admin/answer/[answerId]/page.tsx index 36dedc3d..f6a4aea5 100644 --- a/src/app/(authed)/admin/answer/[answerId]/page.tsx +++ b/src/app/(authed)/admin/answer/[answerId]/page.tsx @@ -9,6 +9,7 @@ import Comments from './_components/Comments'; import adminDashboardTheme from '../../theme/adminDashboardTheme'; import type { ErrorResponse, + GetAnswerLabelsResponse, GetAnswerResponse, GetQuestionsResponse, } from '@/app/api/_schemas/ResponseSchemas'; @@ -27,13 +28,19 @@ const Home = ({ params }: { params: { answerId: number } }) => { : '' ); - if (!answers || !formQuestions) { + const { data: labels, isLoading: isLabelsLoading } = useSWR< + Either + >('/api/answers/labels'); + + if (!answers || !formQuestions || !labels) { return ; } else if ( (!isAnswersLoading && !answers) || (!isFormQuestionsLoading && !formQuestions) || + (!isLabelsLoading && !labels) || answers._tag === 'Left' || - formQuestions._tag === 'Left' + formQuestions._tag === 'Left' || + labels._tag === 'Left' ) { return ; } @@ -51,6 +58,7 @@ const Home = ({ params }: { params: { answerId: number } }) => { ; +// GET /forms/answers/labels +export const getAnswerLabelsResponseSchema = z + .object({ + id: z.number(), + name: z.string(), + }) + .array(); + +export type GetAnswerLabelsResponse = z.infer< + typeof getAnswerLabelsResponseSchema +>; + // GET /forms/answers/:answerId export const getAnswerResponseSchema = z.object({ id: z.number(), diff --git a/src/app/api/answers/labels/route.ts b/src/app/api/answers/labels/route.ts new file mode 100644 index 00000000..08d1ed2f --- /dev/null +++ b/src/app/api/answers/labels/route.ts @@ -0,0 +1,24 @@ +'use server'; + +import { NextResponse } from 'next/server'; +import { BACKEND_SERVER_URL } from '@/env'; +import { getCachedToken } from '@/user-token/mcToken'; +import type { NextRequest } from 'next/server'; + +export async function GET(_: NextRequest) { + const token = await getCachedToken(); + if (!token) { + return NextResponse.redirect('/'); + } + + const response = await fetch(`${BACKEND_SERVER_URL}/forms/answers/labels`, { + method: 'GET', + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}`, + }, + cache: 'no-cache', + }); + + return NextResponse.json(await response.json(), { status: response.status }); +}