Skip to content

Commit

Permalink
feat: add token setting and store setting (#39)
Browse files Browse the repository at this point in the history
* feat: api token header setting

* chore: add zustand

* refactor: change localStorage logic to store method

* COMMENT: add task comment

* refactor: unify userId key naming rules

apply the rules except those set to key values in the post method param
  • Loading branch information
Jeong-jj authored Dec 14, 2024
1 parent a15fc5a commit e138052
Show file tree
Hide file tree
Showing 26 changed files with 231 additions and 148 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"react-router-dom": "5.3.4",
"tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.8"
"zod": "^3.23.8",
"zustand": "^5.0.2"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
Expand Down
26 changes: 26 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/api/answer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const answerAPI = {
list: async (
param: T.GetAnswerListParam
): Promise<AxiosResponse<T.GetAnswerListResponse>> => {
const res = await api.get(`answer/${param.memberId}/list`);
const res = await api.get(`answer/${param.userId}/list`);

return res;
},
Expand All @@ -30,9 +30,9 @@ export const answerAPI = {
return res;
},
getSelfReflectionAnswer: async (
memberId: string
userId: number
): Promise<T.SelfReflectionAnswerResponse> => {
const res = await api.get(`/self-reflection/${memberId}/list`);
const res = await api.get(`/self-reflection/${userId}/list`);
return res.data;
},
};
2 changes: 1 addition & 1 deletion src/api/answer/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type AnswerCreateResponse = BaseResponse<{
export type SelfReflectionAnswerResponse = BaseResponse<SelfReflection>;

export type GetAnswerListParam = {
memberId: number;
userId: number;
};

export type GetAnswerListResponse = BaseResponse<{
Expand Down
29 changes: 27 additions & 2 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import axios, { AxiosInstance } from "axios";
import axios, {
AxiosHeaders,
AxiosInstance,
InternalAxiosRequestConfig,
} from "axios";

const BASE_URL: string = import.meta.env.VITE_API_HOST;
const VERSION = import.meta.env.VITE_API_VERSION;
Expand All @@ -13,5 +17,26 @@ const createAxios = (): AxiosInstance => {
return axios.create({ baseURL: BASE_URL + VERSION, headers: HEADERS });
};

// TODO: token 세팅 후 코드 수정 필요
const token = "";
const interceptors = (instance: AxiosInstance): AxiosInstance => {
instance.interceptors.request.use(
async (config: InternalAxiosRequestConfig) => {
if (!config.headers) {
config.headers = new AxiosHeaders();
}
config.headers.Authorization = `Bearer ${token}`;
return config;
},
(error) => {
return Promise.reject(error);
}
);
return instance;
};

// No token
export const api: AxiosInstance = createAxios();
export const api = createAxios();

// With token
export const apiWithToken = interceptors(api);
6 changes: 3 additions & 3 deletions src/api/link/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import * as T from "./type";
import { api } from "..";

export async function getLink(
questionId: string,
memberId: string,
questionId: number,
userId: number,
params: T.ShareLinkParam
): Promise<T.ShareLinkResponse> {
const res = await api.get(`/question/${questionId}/share-info/${memberId}`, {
const res = await api.get(`/question/${questionId}/share-info/${userId}`, {
params,
});
return res.data;
Expand Down
4 changes: 2 additions & 2 deletions src/api/member/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export const memberAPI = {
return res;
},
search: async (
memberId: string
userId: number
): Promise<AxiosResponse<T.MemberSearchResponse>> => {
const res = await api.get(`/member/${memberId}`);
const res = await api.get(`/member/${userId}`);

return res;
},
Expand Down
16 changes: 6 additions & 10 deletions src/api/self-reflection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,21 @@ import { api } from "..";
import * as T from "./type";

export const selfReflection = {
getCommonQuestions: async (
memberId: string
): Promise<AxiosResponse<T.QuestionResponse>> => {
return api.get("/self-reflection/common-question", {
params: { memberId },
});
getCommonQuestions: async (): Promise<AxiosResponse<T.QuestionResponse>> => {
return api.get("/self-reflection/common-question");
},

getSelfReflection: async (
memberId: string
userId: number
): Promise<AxiosResponse<T.GetReflectionAnswerResponse>> => {
return api.get(`/self-reflection/${memberId}/list`);
return api.get(`/self-reflection/${userId}/list`);
},

submitReflections: async (
memberId: string,
userId: number,
reflections: T.ReflectionRequest[]
) => {
return api.post(`/self-reflection/${memberId}`, {
return api.post(`/self-reflection/${userId}`, {
reflections,
});
},
Expand Down
8 changes: 4 additions & 4 deletions src/api/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import { api } from "@/api";

export const userInfo = {
getSettings: async (
memberId: string
userId: number
): Promise<AxiosResponse<MemberResponse>> => {
return api.get(`/member/${memberId}`);
return api.get(`/member/${userId}`);
},

updateSettings: async (
memberId: string,
userId: number,
settings: MemberSettings
): Promise<AxiosResponse<MemberResponse>> => {
return api.put(`/member/${memberId}`, settings);
return api.put(`/member/${userId}`, settings);
},
};
12 changes: 7 additions & 5 deletions src/components/common/snowFall.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { answerAPI } from "@/api/answer";
import { useEffect, useState } from "react";
import { answerAPI } from "@/api/answer";

import { useUserStore } from "@/store/userStore";

const Snowfall = () => {
const snowflakes = Array.from({ length: 50 });

const [snowColorArray, setSnowColorArray] = useState<string[]>([]);

const handleSnowflakeColor = async (memberId: number) => {
await answerAPI.list({ memberId }).then((res) => {
const handleSnowflakeColor = async (userId: number) => {
await answerAPI.list({ userId }).then((res) => {
const data = res.data.data;

const colorArr = data.list?.map((answer) => answer.colorCode);
Expand All @@ -17,9 +19,9 @@ const Snowfall = () => {
});
};

const userId = Number(localStorage.getItem("userId"));
const { userId } = useUserStore();
useEffect(() => {
handleSnowflakeColor(userId);
if (userId) handleSnowflakeColor(userId);
}, [userId]);

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/display/DirectLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function DirectLogin() {
onClick={() =>
history.push({
pathname: "/member-login",
state: { memberId: DUMMY_MEMBER_ID },
state: { userId: DUMMY_MEMBER_ID },
})
}
>
Expand Down
22 changes: 8 additions & 14 deletions src/components/share/ShareButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,21 @@ import { SHARE_LINK_PARAM } from "@/constant/link";

type Props = {
className?: string;
memberId: number;
userId: number;
questionId: number;
};

export default function ShareButton({
className,
memberId,
questionId,
}: Props) {
export default function ShareButton({ className, userId, questionId }: Props) {
const { toast } = useToast();

const copyShareLinkAddress = () => {
getLink(String(questionId), String(memberId), SHARE_LINK_PARAM).then(
(data) => {
navigator.clipboard.writeText(data.data.url).then(() => {
toast({
description: "링크가 복사되었습니다",
});
getLink(questionId, userId, SHARE_LINK_PARAM).then((data) => {
navigator.clipboard.writeText(data.data.url).then(() => {
toast({
description: "링크가 복사되었습니다",
});
}
);
});
});
};

return (
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useSelfReflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { answerAPI } from "@/api/answer";
import { SelfReflection } from "@/types/self-reflection";
import { useToast } from "@/hooks/use-toast";

export function useSelfReflection(memberId: string) {
export function useSelfReflection(userId: number) {
const [selfReflection, setSelfReflection] = useState<SelfReflection>([]);
const [isLoading, setIsLoading] = useState(true);
const { toast } = useToast();

useEffect(() => {
const fetchSelfReflection = async () => {
try {
const response = await answerAPI.getSelfReflectionAnswer(memberId);
const response = await answerAPI.getSelfReflectionAnswer(userId);
setSelfReflection(response.data);
} catch (error) {
toast({
Expand All @@ -25,7 +25,7 @@ export function useSelfReflection(memberId: string) {
};

fetchSelfReflection();
}, [memberId]);
}, [userId, toast]);

return {
selfReflection,
Expand Down
28 changes: 17 additions & 11 deletions src/pages/answer-create/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { useState, useMemo } from "react";
import { useLocation } from "react-router-dom";

import { answerAPI } from "@/api/answer";
import { memberAPI } from "@/api/member";

import { ColorPicker } from "@/components/color/ColorPicker";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { MOCK_MEMBER } from "../_mock/data/member";
import { useState, useMemo } from "react";
import UnderlineInput from "@/components/input/UnderlineInput";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import UnderlineInput from "@/components/input/UnderlineInput";
import { COLOR_CODE_LIST } from "@/constant/color";
import { answerAPI } from "@/api/answer";
import { DirectLogin } from "@/components/display/DirectLogin";
import { memberAPI } from "@/api/member";

import { MOCK_MEMBER } from "../_mock/data/member";
import { COLOR_CODE_LIST } from "@/constant/color";

import { useUserStore } from "@/store/userStore";

function useQuery() {
const { search } = useLocation();
Expand All @@ -23,27 +27,29 @@ function useQuery() {

export default function AnswerCreate() {
const query = useQuery();
// const memberId = query.get("memberId") as string;

// TODO: questionId로 질문 정보 조회하는 api 연결 필요
const questionId = query.get("questionId") as string;

const [colorCode, setColorCode] = useState<string | undefined>(undefined);
const [content, setContent] = useState<string>("");
const [userNickname, setUserNicname] = useState<string>("");
const [senderName, setSenderName] = useState<string>("");

const storedId = localStorage.getItem("userId");
const { userId } = useUserStore();

if (!storedId) {
if (!userId) {
// TODO: 추후 질문에 설정된 옵션에 따라 login 체크 여부 나뉘도록 설정 필요
return <DirectLogin />;
}

const sendAnswer = async () => {
await memberAPI.search(storedId).then((res) => {
await memberAPI.search(userId).then((res) => {
const userInfo = res.data.data;
setUserNicname(userInfo.nickname);

answerAPI.create({
memberId: Number(storedId),
memberId: userId,
questionId: questionId,
nickname: userNickname,
sender: senderName,
Expand Down
Loading

0 comments on commit e138052

Please sign in to comment.