Skip to content

Commit

Permalink
Refactor/api provider (#149)
Browse files Browse the repository at this point in the history
* rename AuthContext to ApiProvider

* feat: ApiProvider 도입 철회, axios의 client만 도입

* feat: 흩어져 있던 axios 모음

* error handling

* feat: axios client로 모두 수정
  • Loading branch information
Lukaid-dev authored Dec 6, 2023
1 parent 99265cc commit d88cdce
Show file tree
Hide file tree
Showing 20 changed files with 122 additions and 108 deletions.
2 changes: 1 addition & 1 deletion client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Outlet } from 'react-router-dom';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';

import { AuthProvider } from './contexts/AuthContext';
import { AuthProvider } from './contexts/AuthProvider';
import { ThemeProvider } from './contexts/ThemeProvider';
import ThemeComponent from './components/temp/ThemedComponent';

Expand Down
16 changes: 0 additions & 16 deletions client/src/apis/Auth.ts

This file was deleted.

6 changes: 6 additions & 0 deletions client/src/apis/apiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import axios, { AxiosInstance } from 'axios';

export const apiClient: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_BASE_URL as string,
withCredentials: true,
});
22 changes: 12 additions & 10 deletions client/src/apis/createRoom.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import axios from 'axios';
import { AxiosError } from 'axios';
import { RoomCreateType } from '../types/RoomCreateType';

const VITE_BASE_URL = import.meta.env.VITE_BASE_URL as string;
import { apiClient } from './apiClient';

export async function createRoom(): Promise<RoomCreateType | undefined> {
const response = await axios.post(
`${VITE_BASE_URL}/room`,
{},
{ withCredentials: true },
);

return response.data;
try {
const { data } = await apiClient.post('/room', {});
return data;
} catch (error) {
if (error instanceof AxiosError) {
// TODO: 이거 session로직 수정되면 여기도 고쳐야 됨
// 세션에서 현재 유저가 방에 참가중인지, 어떤 방에 참가중인지 정보를 받아 올 수 있어야 함
alert(error.response!.data.message);
}
}
}
10 changes: 6 additions & 4 deletions client/src/apis/exitRoom.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import axios from 'axios';

const VITE_BASE_URL = import.meta.env.VITE_BASE_URL as string;
import { apiClient } from './apiClient';

export async function exitRoom() {
await axios.post(`${VITE_BASE_URL}/room/exit`, {}, { withCredentials: true });
try {
await apiClient.post('/room/exit');
} catch (error) {
console.log(error);
}
}
11 changes: 11 additions & 0 deletions client/src/apis/getSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CreateUser } from '../types/CreateUserType';
import { apiClient } from './apiClient';

export async function getSession(): Promise<CreateUser | undefined> {
try {
const { data }: { data: CreateUser } = await apiClient.get('/session');
return data;
} catch (error) {
console.log(error);
}
}
16 changes: 6 additions & 10 deletions client/src/apis/joinRoom.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import axios from 'axios';

const VITE_BASE_URL = import.meta.env.VITE_BASE_URL as string;
import { apiClient } from './apiClient';

export async function joinRoom(roomCode: string) {
await axios.post(
`${VITE_BASE_URL}/room/join`,
{ code: roomCode },
{
withCredentials: true,
},
);
try {
await apiClient.post('/room/join', { code: roomCode });
} catch (error) {
console.log(error);
}
}
9 changes: 9 additions & 0 deletions client/src/apis/logout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { apiClient } from './apiClient';

export async function logout() {
try {
await apiClient.get('/auth/logout');
} catch (error) {
console.log(error);
}
}
14 changes: 14 additions & 0 deletions client/src/apis/mockLogin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { apiClient } from './apiClient';

type mockUser = {
username: string;
password: string;
};

export async function mockLoginApi(mockUser: mockUser) {
try {
return await apiClient.post('/auth/mock', mockUser);
} catch (error) {
console.log(error);
}
}
25 changes: 12 additions & 13 deletions client/src/apis/searchProblem.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import axios from 'axios';
import { ProblemResponse } from '../types/Problem';

export async function searchProblem(searchKeyword: string): Promise<ProblemResponse[]> {
const VITE_BASE_URL = import.meta.env.VITE_BASE_URL as string;
import { apiClient } from './apiClient';

if(!searchKeyword) return Promise.resolve([]);
export async function searchProblem(
searchKeyword: string,
): Promise<ProblemResponse[]> {
if (!searchKeyword) return Promise.resolve([]);

return await axios
.get(`${VITE_BASE_URL}/problem`, {
try {
const { data } = await apiClient.get('/problem', {
params: {
searchKeyword,
},
})
.then((res) => {
return res.data || [];
})
.catch((err) => {
console.log(err);
return [];
});
return data;
} catch (error) {
console.log(error);
return [];
}
}
4 changes: 2 additions & 2 deletions client/src/components/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FaArrowRight } from 'react-icons/fa6';
import Message from './Message';
import { useAuthContext } from '../contexts/AuthProvider';
import { ChatEvent, MessageInterface } from '../types/Message';
import { useAuthContext } from '../contexts/AuthContext';
import { Socket } from 'socket.io-client';

// TODO: userColor -> 서버에서 설정
Expand Down Expand Up @@ -36,7 +36,7 @@ export default function Chat({
username: user?.username || 'Anonymous',
body: inputText,
chatEvent: ChatEvent.Message,
color: 'text-purple', // TODO: 서버에서 설정
color: 'text-purple', // TODO: 클라에서 랜덤 설정
};

socket.emit('chat-message', newChatMessage);
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/Profile.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useAuthContext } from '../contexts/AuthContext';
import { useAuthContext } from '../contexts/AuthProvider';

export default function Profile() {
const { user } = useAuthContext();
Expand All @@ -11,7 +11,7 @@ export default function Profile() {
src={user!.avatarUrl}
alt="프로필 이미지"
/>
<p className="text-text_default text-lg font-semibold">
<p className="text-lg font-semibold text-text_default">
{user!.username}
</p>
</div>
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/buttons/LogoutButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useAuthUpdateContext } from '../../contexts/AuthContext';
import { useAuthUpdateContext } from '../../contexts/AuthProvider';

export default function LogoutButton() {
const { onLogout } = useAuthUpdateContext();
Expand Down
11 changes: 5 additions & 6 deletions client/src/components/buttons/RoomCreateButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ export default function RoomCreateButton() {
try {
const roomInfo: RoomCreateType | undefined = await createRoom();
if (roomInfo === undefined) {
setTimeout(() => {
console.log(roomInfo);
alert('방 생성에 실패했습니다.');
setIsLoading(false);
}, 1000);

// setTimeout(() => {
// alert('방 생성에 실패했습니다.');
//
// }, 1000);
setIsLoading(false);
return;
}
const roomCode = roomInfo.code;
Expand Down
19 changes: 8 additions & 11 deletions client/src/components/temp/MockLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import axios from 'axios';
import { mockLoginApi } from '../../apis/mockLogin';

export default function MockLogin() {
const baseURL = import.meta.env.VITE_BASE_URL;

async function mockLogin({ id }: { id: string }) {
const mockUser = {
username: `mock${id}`,
password: `mock${id}`,
};
const response = await axios.post(`${baseURL}/auth/mock`, mockUser, {
withCredentials: true,
});
if (response.status === 201) {
const response = await mockLoginApi(mockUser);
console.log(response);
if (response?.status === 201) {
console.log(response.data);
// AuthProvider의 useEffect가 실행되지 않아서 새로고침을 해줘야 함
// 원래라면 AuthProvider에 따로 메서드를 만들어줘야하는게 맞는데 mock이라서 그냥 새로고침으로 대체
Expand All @@ -23,31 +20,31 @@ export default function MockLogin() {
<div className="flex gap-2">
<button
id="1"
className="text-text_default bg-default_black my-2 flex items-center gap-2 rounded-lg px-4 py-2.5 text-sm hover:hover:bg-opacity-50"
className="my-2 flex items-center gap-2 rounded-lg bg-default_black px-4 py-2.5 text-sm text-text_default hover:hover:bg-opacity-50"
onClick={() => {
mockLogin({ id: '1' });
}}>
Mock 1
</button>
<button
id="2"
className="text-text_default bg-default_black my-2 flex items-center gap-2 rounded-lg px-4 py-2.5 text-sm hover:hover:bg-opacity-50"
className="my-2 flex items-center gap-2 rounded-lg bg-default_black px-4 py-2.5 text-sm text-text_default hover:hover:bg-opacity-50"
onClick={() => {
mockLogin({ id: '2' });
}}>
Mock 2
</button>
<button
id="3"
className="text-text_default bg-default_black my-2 flex items-center gap-2 rounded-lg px-4 py-2.5 text-sm hover:hover:bg-opacity-50"
className="my-2 flex items-center gap-2 rounded-lg bg-default_black px-4 py-2.5 text-sm text-text_default hover:hover:bg-opacity-50"
onClick={() => {
mockLogin({ id: '3' });
}}>
Mock 3
</button>
<button
id="4"
className="text-text_default bg-default_black my-2 flex items-center gap-2 rounded-lg px-4 py-2.5 text-sm hover:hover:bg-opacity-50"
className="my-2 flex items-center gap-2 rounded-lg bg-default_black px-4 py-2.5 text-sm text-text_default hover:hover:bg-opacity-50"
onClick={() => {
mockLogin({ id: '4' });
}}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { useNavigate } from 'react-router-dom';
import { createContext, useContext, useEffect, useState } from 'react';
import {
ReactNode,
createContext,
useContext,
useEffect,
useState,
} from 'react';
import { CreateUser } from '../types/CreateUserType';
import { getSession, logout } from '../apis/Auth';
import { logout } from '../apis/logout';
import { getSession } from '../apis/getSession';

interface AuthContextType {
user: CreateUser | null;
Expand All @@ -11,39 +18,30 @@ interface AuthUpdateType {
onLogout: () => void;
}

interface AuthProviderProps {
children: ReactNode;
}

const AuthContext = createContext<AuthContextType>({} as AuthContextType);
const AuthUpdateContext = createContext<AuthUpdateType>({} as AuthUpdateType);

export const AuthProvider = ({ children }: { children: JSX.Element }) => {
export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
const navigate = useNavigate();

const [user, setUser] = useState<CreateUser | null>(null);

const onLogout = () => {
try {
logout();
setUser(null);
navigate('/');
} catch (err) {
console.error(err);
throw err;
}
logout();
setUser(null);
navigate('/');
};

useEffect(() => {
(async () => {
try {
const user = await getSession();

if (user) {
setUser(user);
} else {
setUser(null);
}
} catch (error) {
console.error(error);
getSession().then((data) => {
if (data) {
setUser(data);
}
})();
});
}, []);

return (
Expand Down
7 changes: 3 additions & 4 deletions client/src/contexts/ThemeProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ type Theme =
| 'atom-one-light'
| 'github-dark'
| 'github-light';

type ThemeContextType = {
theme: Theme;
toggleTheme: () => void;
};

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
const ThemeContext = createContext<ThemeContextType>({} as ThemeContextType);

interface ThemeProviderProps {
children: ReactNode;
Expand All @@ -27,17 +28,15 @@ interface ThemeProviderProps {
const localStorageKey = 'theme';

export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
// Retrieve theme from localStorage or use 'default' as the default value
const storedTheme = localStorage.getItem(localStorageKey) as Theme | null;
const [theme, setTheme] = useState<Theme>(storedTheme || 'atom-one-dark');

useEffect(() => {
// Update data-theme attribute when the theme changes
document.documentElement.setAttribute('data-theme', theme);
// Save the theme to localStorage
localStorage.setItem(localStorageKey, theme);
}, [theme]);

// TODO: change setting function
const toggleTheme = () => {
setTheme((prevTheme) => {
switch (prevTheme) {
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useNavigate } from 'react-router-dom';
import { useAuthContext } from '../contexts/AuthContext';
import { useAuthContext } from '../contexts/AuthProvider';
import GithubLoginButton from '../components/buttons/GithubLoginButton';
import { useEffect } from 'react';
import MockLogin from '../components/temp/MockLogin';
Expand Down
Loading

0 comments on commit d88cdce

Please sign in to comment.