From 8836a53921971cae3bb075a3c2bda0c6a0c491c7 Mon Sep 17 00:00:00 2001
From: naoki1510 <15890587+naoki1510@users.noreply.github.com>
Date: Thu, 7 Mar 2024 22:10:49 +0900
Subject: [PATCH 1/2] =?UTF-8?q?=E6=AD=A3=E7=AD=94=E3=81=A8=E8=AA=A4?=
=?UTF-8?q?=E7=AD=94=E3=81=AE=E8=A1=A8=E7=A4=BA=E3=82=92=E6=94=B9=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
api/app/controllers/questions_controller.rb | 7 +---
api/app/views/choices/_choice.json.jbuilder | 4 +--
client/src/api/choice.ts | 3 ++
.../src/components/answers/CreateAnswer.tsx | 34 +++++++++++--------
client/src/components/common/Header.tsx | 22 +++++++++---
.../src/components/questions/QuestionCard.tsx | 23 ++++++++-----
client/src/components/users/CreateUser.tsx | 9 +++--
client/src/recoil/localStorage.ts | 1 +
client/src/recoil/passwordState.ts | 6 ++--
client/src/recoil/userIdState.ts | 6 ++++
10 files changed, 74 insertions(+), 41 deletions(-)
create mode 100644 client/src/recoil/userIdState.ts
diff --git a/api/app/controllers/questions_controller.rb b/api/app/controllers/questions_controller.rb
index b927a964..776f4105 100644
--- a/api/app/controllers/questions_controller.rb
+++ b/api/app/controllers/questions_controller.rb
@@ -1,6 +1,6 @@
class QuestionsController < ApplicationController
before_action :set_question, only: %i[ show update destroy start end ]
- before_action :set_show_correct, :set_show_answers, only: %i[ index show start end ]
+ before_action :set_show_correct, only: %i[ index show start end ]
# GET /questions
def index
@@ -73,9 +73,4 @@ def question_params
def set_show_correct
@is_show_correct = params[:show_correct].present?
end
-
- # Whether to display answers
- def set_show_answers
- @is_show_answers = params[:show_answers].present?
- end
end
diff --git a/api/app/views/choices/_choice.json.jbuilder b/api/app/views/choices/_choice.json.jbuilder
index 12751b60..5caa0bfb 100644
--- a/api/app/views/choices/_choice.json.jbuilder
+++ b/api/app/views/choices/_choice.json.jbuilder
@@ -1,5 +1,5 @@
json.extract! choice, :id, :title, :description, :image, :question_id
json.is_correct choice.is_correct if @is_show_correct
-json.answer do
- json.array! choice.answers, partial: 'answers/answer', as: :answer if @is_show_answers
+json.answers do
+ json.array! choice.answers, partial: 'answers/answer', as: :answer
end
\ No newline at end of file
diff --git a/client/src/api/choice.ts b/client/src/api/choice.ts
index f3ccff4d..a404f590 100644
--- a/client/src/api/choice.ts
+++ b/client/src/api/choice.ts
@@ -1,5 +1,6 @@
import { postHeaders } from "api/headers";
import host from "api/host";
+import { Answer } from "./answer";
export type Choice = {
id?: number;
@@ -8,6 +9,7 @@ export type Choice = {
image: string;
display_order?: number;
is_correct?: boolean;
+ answers: Answer[];
};
export const createEmptyChoice = (questionId?: number): Choice => {
@@ -16,6 +18,7 @@ export const createEmptyChoice = (questionId?: number): Choice => {
description: "",
image: "",
is_correct: false,
+ answers: [],
};
};
diff --git a/client/src/components/answers/CreateAnswer.tsx b/client/src/components/answers/CreateAnswer.tsx
index 677b9bde..83c8094e 100644
--- a/client/src/components/answers/CreateAnswer.tsx
+++ b/client/src/components/answers/CreateAnswer.tsx
@@ -1,12 +1,12 @@
import {
Box,
+ Button,
Card,
CardBody,
HStack,
Heading,
- IconButton,
Text,
- VStack
+ VStack,
} from "@chakra-ui/react";
import { createAnswer } from "api/answer";
import { Choice } from "api/choice";
@@ -18,14 +18,17 @@ import locations from "locations";
import { memo, useCallback, useEffect, useState } from "react";
import { IoExit } from "react-icons/io5";
import { useNavigate } from "react-router-dom";
+import { useRecoilState } from "recoil";
+import userIdState from "recoil/userIdState";
import AnswerForm from "./AnswerForm";
let previousQuestionIds: number[] = [];
export default memo(function CreateAnswer() {
const navigate = useNavigate();
+ const [userId, setUserID] = useRecoilState(userIdState);
useEffect(() => {
- if (!localStorage.getItem("userId") === null) {
+ if (userId === undefined) {
navigate(locations.createUser);
}
}, [navigate]);
@@ -37,24 +40,24 @@ export default memo(function CreateAnswer() {
);
const { questions: lastQuestions, fetchQuestions: fetchLastQuestions } =
useQuestions(new URLSearchParams({ last: "true", show_correct: "true" }));
- const { user, fetchUser } = useUser(localStorage.getItem("userId") || "");
+ const { user, fetchUser } = useUser(userId || "");
useEffect(() => {
if (!questions) return;
- previousQuestionIds.forEach((id) => {
+ previousQuestionIds.map(async (id) => {
if (questions.every((question) => question.id !== id)) {
- Promise.all(
+ await Promise.all(
selectedChoices
.filter((choice) => choice.question_id === id)
.map((choice) => {
- if (choice.id && localStorage.getItem("userId"))
+ if (choice.id && userId)
return createAnswer({
choice_id: choice.id,
- user_id: Number(localStorage.getItem("userId")),
+ user_id: userId,
});
})
- ).then(() => fetchUser());
+ );
fetchLastQuestions();
}
});
@@ -74,7 +77,7 @@ export default memo(function CreateAnswer() {
}, [fetchQuestions, questions]);
const handleLogout = useCallback(() => {
- localStorage.removeItem("userId");
+ setUserID(undefined);
navigate(locations.createUser);
}, [navigate]);
@@ -91,11 +94,13 @@ export default memo(function CreateAnswer() {
- }
+ }
onClick={handleLogout}
- />
+ colorScheme="red"
+ >
+ ログアウト
+
@@ -111,7 +116,6 @@ export default memo(function CreateAnswer() {
))
) : lastQuestions?.length ? (
<>
- 回答済みの問題
{lastQuestions.map((question) => (
diff --git a/client/src/components/common/Header.tsx b/client/src/components/common/Header.tsx
index b1c012ed..985fc999 100644
--- a/client/src/components/common/Header.tsx
+++ b/client/src/components/common/Header.tsx
@@ -9,6 +9,7 @@ import { useAuthorize } from "./Authorize";
type MenuData = {
label: string;
href: string;
+ admin?: boolean;
};
const menus: MenuData[] = [
@@ -16,13 +17,20 @@ const menus: MenuData[] = [
label: "Play",
href: locations.createUser,
},
+ {
+ label: "Admin",
+ href: locations.listQuestions,
+ admin: false,
+ },
{
label: "Questions",
href: locations.listQuestions,
+ admin: true,
},
{
label: "Users",
href: locations.listQuestions,
+ admin: true,
},
];
@@ -42,11 +50,15 @@ export default memo(function Header() {
Quiz
} alignItems={"stretch"}>
- {menus.map((menu) => (
-
- ))}
+ {menus
+ .filter(
+ (menu) => menu.admin === undefined || menu.admin === authorized
+ )
+ .map((menu) => (
+
+ ))}
{authorized && (
+ }
+ variant={"outline"}
+ >
+ 削除
+
)}
diff --git a/client/src/components/questions/ShowQuestion.tsx b/client/src/components/questions/ShowQuestion.tsx
index 1f85a9bd..3316e1f0 100644
--- a/client/src/components/questions/ShowQuestion.tsx
+++ b/client/src/components/questions/ShowQuestion.tsx
@@ -1,11 +1,11 @@
-import { deleteQuestion, useQuestion } from "api/questions";
+import { Button, HStack, VStack } from "@chakra-ui/react";
+import { useQuestion } from "api/questions";
import Loading from "components/common/Loading";
import locations from "locations";
-import { memo, useCallback } from "react";
+import { memo } from "react";
+import { IoChevronBack } from "react-icons/io5";
import { Link, useNavigate, useParams } from "react-router-dom";
import QuestionCard from "./QuestionCard";
-import { Button, HStack, List, VStack } from "@chakra-ui/react";
-import { IoChevronBack, IoPencil, IoTrash } from "react-icons/io5";
export default memo(function ShowQuestion() {
const navigate = useNavigate();
@@ -16,16 +16,10 @@ export default memo(function ShowQuestion() {
}
const { question, setQuestion } = useQuestion(
- Number(id),
+ id,
new URLSearchParams({ show_correct: "true" })
);
- const handleDelete = useCallback(() => {
- deleteQuestion(id).then(() => {
- navigate(locations.listQuestions);
- });
- }, []);
-
return question ? (
戻る
- }
- colorScheme="blue"
- ml={"auto"}
- >
- 編集
-
- }>
- 削除
-
- {}
) : (