Skip to content

Commit

Permalink
feat: 파일 라우팅 설정 및 api 로직 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
wecaners committed Dec 17, 2023
1 parent 32d9ad7 commit 11510a4
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 129 deletions.
31 changes: 31 additions & 0 deletions api/services/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
getRefreshToken,
setAccessToken,
setRefreshToken,
} from "@/utils/localStorage";
import axios from "axios";

const BASE_URL = "https://bootcamp-api.codeit.kr";
Expand All @@ -6,12 +11,36 @@ const SAMPLE_FOLDER_ENDPOINT = "/api/sample/folder";
const USERS_ENDPOINT = "/api/users";
const SIGNIN_ENDPOINT = "/api/sign-in";
const SIGNUP_ENDPOINT = "/api/sign-up";
const FOLDER_ENDPOINT = `/api/folders`;
const LINKS_ENDPOINT = `/api/links`;

const instance = axios.create({
baseURL: "https://bootcamp-api.codeit.kr",
timeout: 3000,
});

instance.interceptors.response.use(
(res) => res,
async (error) => {
const originalRequest = error.config;
let res;
if (error.response?.status === 401 && !originalRequest._retry) {
res = await instance.post(
"/api/refresh-token",
{
refresh_token: getRefreshToken(),
},
{ _retry: true } as any
);
setAccessToken(res?.data.data.accessToken);
setRefreshToken(res?.data.data.refreshToken);
originalRequest._retry = true;
return instance(originalRequest);
}
return Promise.reject(error);
}
);

export {
BASE_URL,
SAMPLE_USER_ENDPOINT,
Expand All @@ -20,4 +49,6 @@ export {
instance,
SIGNIN_ENDPOINT,
SIGNUP_ENDPOINT,
FOLDER_ENDPOINT,
LINKS_ENDPOINT,
};
4 changes: 1 addition & 3 deletions components/addLinkInput/AddLinkInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ const AddLinkInput = forwardRef<HTMLDivElement, AddLinkInputProps>(
{folders.map((folder) => (
<Dialog.FolderList key={folder.id}>
<span className="dialog-folder-name">{folder.name}</span>
<span className="dialog-folder-count">
{folder.link.count}개 링크
</span>
<span className="dialog-folder-count">개 링크</span>
</Dialog.FolderList>
))}
<Dialog.Button isAddButton>추가하기</Dialog.Button>
Expand Down
31 changes: 19 additions & 12 deletions components/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import styles from "./header.module.css";
import { FolderInfo, SampleFolder } from "../../types/types";
import Image from "next/image";
import useUserStore from "@/hooks/useStore";

interface HeaderProps {
folderInfo: SampleFolder;
folderName: string;
}

export default function Header({ folderInfo }: HeaderProps) {
export default function Header({ folderName }: HeaderProps) {
const { user } = useUserStore();
const name = user[0]?.name;

return (
<header className={styles.header}>
<div className={styles.userInfoBox}>
<Image
src={folderInfo?.folder.owner.profileImageSource}
alt="profile"
className={styles.profileImage}
width={24}
height={24}
/>
<span className={styles.userName}>{folderInfo?.folder.owner.name}</span>
{user?.map((item) => (
<Image
key={item.id}
src={item.image_source}
alt="profile"
className={styles.profileImage}
width={24}
height={24}
/>
))}

<span className={styles.userName}>{name}</span>
</div>
<span className={styles.folderName}>{folderInfo?.folder.name}</span>
<span className={styles.folderName}>{folderName}</span>
</header>
);
}
37 changes: 12 additions & 25 deletions components/layout/nav/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,25 @@
import React, { useEffect, useState } from "react";
import styles from "./nav.module.css";
import logo from "@/public/icons/logo.svg";
import { SampleUser } from "../../../types/types";
import { User } from "../../../types/types";
import { useRouter } from "next/router";
import Link from "next/link";
import Image from "next/image";
import axios from "axios";

interface NavProps {
userProfile: SampleUser[];
}

export const getStaticProps = async () => {
// 여기 getStaticProps로 전달한 userProfile이 계속해서 undefined가 뜨는 이유 ???
const response = await axios.get(
"https://bootcamp-api.codeit.kr/api/users/1"
);
const userProfile = response.data.data;

return {
props: {
userProfile,
},
};
};
import { USERS_ENDPOINT, instance } from "@/api/services/config";
import { getAccessToken } from "@/utils/localStorage";

export default function Nav() {
const [userProfile, setUserProfile] = useState<SampleUser[]>();
const router = useRouter();
const isFolderPage = router.pathname === "/folder";
const [userProfile, setUserProfile] = useState<User[]>([]);

const fetchUsers = async () => {
const res = await axios.get("https://bootcamp-api.codeit.kr/api/users/1");
const user = res.data.data;
const res = await instance.get(USERS_ENDPOINT, {
headers: {
Authorization: `Bearer ${getAccessToken()}`,
},
});
const user = res?.data.data;
setUserProfile(user);
};

Expand All @@ -41,7 +28,7 @@ export default function Nav() {
}, []);

return (
<div>
<>
<nav className={isFolderPage ? styles.gnbContainer : styles.gnbFolder}>
<Link href="/">
<Image
Expand Down Expand Up @@ -71,6 +58,6 @@ export default function Nav() {
</Link>
)}
</nav>
</div>
</>
);
}
32 changes: 30 additions & 2 deletions components/signinForm/SigninForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Input } from "../input/Input";
import PasswordInput from "../passwordInput/PasswordInput";
import styles from "./SignInForm.module.css";
import Button from "../button/Button";
import { SIGNIN_ENDPOINT, instance } from "@/api/services/config";
import { useRouter } from "next/router";
import axios from "axios";
import {
Expand All @@ -12,7 +11,17 @@ import {
EMAIL_PATTERN,
PASSWORD_PATTERN,
} from "@/constants/authConstant";
import { setAccessToken } from "@/utils/localStorage";
import {
SIGNIN_ENDPOINT,
USERS_ENDPOINT,
instance,
} from "@/api/services/config";
import {
getAccessToken,
setAccessToken,
setRefreshToken,
} from "@/utils/localStorage";
import useUserStore from "@/hooks/useStore";

export interface FormValues {
email: string;
Expand All @@ -29,6 +38,22 @@ export function SigninForm() {
setError,
} = useForm<FormValues>({ mode: "onBlur" });

const { setUser } = useUserStore();

const getUser = async () => {
try {
const res = await instance.get(USERS_ENDPOINT, {
headers: {
Authorization: `Bearer ${getAccessToken()}`,
},
});
const nextUser = res?.data.data;
setUser(nextUser);
} catch (error) {
console.error(error);
}
};

const onSubmit = handleSubmit(async (data: FormValues) => {
let res;
try {
Expand All @@ -37,7 +62,10 @@ export function SigninForm() {
password: data.password,
});
const accessToken = res?.data.data.accessToken;
const refreshToken = res?.data.data.refreshToken;
setAccessToken(accessToken);
setRefreshToken(refreshToken);
await getUser();
res?.status === 200 && router.push("/folder");
} catch (error) {
if (axios.isAxiosError(error) && error.response?.status === 400) {
Expand Down
50 changes: 50 additions & 0 deletions context/AuthProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { SIGNIN_ENDPOINT, instance } from "@/api/services/config";
import { FormValues } from "@/components/signinForm/SigninForm";
import { setAccessToken } from "@/utils/localStorage";
import { useRouter } from "next/router";
import { ReactNode, createContext, useContext, useState } from "react";

interface AuthProviderProps {
children: ReactNode;
}

const AuthContext = createContext({
signin: async (data: FormValues) => {},
});

export function AuthProvider({ children }: AuthProviderProps) {
const router = useRouter();

const signin = async (data: FormValues) => {
let res;
try {
res = await instance.post(`${SIGNIN_ENDPOINT}`, {
email: data.email,
password: data.password,
});
const accessToken = res?.data.data.accessToken;
setAccessToken(accessToken);
res?.status === 200 && router.push("/folder");
} catch (error) {
console.error(error);
}
};
return (
<AuthContext.Provider
value={{
signin,
}}
>
{children}
</AuthContext.Provider>
);
}

export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("반드시 AuthProvider 안에서 사용해야 합니다.");
}

return context;
};
22 changes: 22 additions & 0 deletions hooks/useStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { User } from "@/types/types";
import { create } from "zustand";
import { persist } from "zustand/middleware";

interface UserState {
user: User[];
setUser: (payload: User[]) => void;
}

const useUserStore = create<UserState>()(
persist(
(set) => ({
user: [],
setUser: (payload) => set((state) => ({ user: (state.user = payload) })),
}),
{
name: "userData",
}
)
);

export default useUserStore;
4 changes: 4 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const nextConfig = {
protocol: "https",
hostname: "static.cdninstagram.com",
},
{
protocol: "https",
hostname: "avatars.githubusercontent.com",
},
],
},
};
Expand Down
Loading

0 comments on commit 11510a4

Please sign in to comment.