diff --git a/src/apis/auth.api.ts b/src/apis/auth.api.ts index 6cabed1..3edd653 100644 --- a/src/apis/auth.api.ts +++ b/src/apis/auth.api.ts @@ -1,6 +1,5 @@ -import { LoginProps } from '@/pages/LoginPage'; import { JoinProps } from '@/pages/JoinPage'; -import httpClient from './http.api'; +import { httpClient } from './http.api'; export const join = async (data: JoinProps) => { const response = await httpClient.post('/api/users/join', data); @@ -12,11 +11,3 @@ export interface LoginResponse { success: boolean; token?: string; } - -export const login = async (data: LoginProps) => { - const response = await httpClient.post( - '/api/users/login', - data - ); - return response.data; -}; diff --git a/src/apis/http.api.ts b/src/apis/http.api.ts index a532349..fe233f9 100644 --- a/src/apis/http.api.ts +++ b/src/apis/http.api.ts @@ -1,11 +1,6 @@ -import axios, { - AxiosInstance, - AxiosRequestConfig, - AxiosHeaders, - AxiosRequestHeaders, -} from 'axios'; +import axios, { AxiosRequestConfig } from 'axios'; -const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3333'; +const BASE_URL = import.meta.env.VITE_API_BASE_URL; const DEFAULT_TIMEOUT = 30000; // 요청 제한 시간 // 토큰 관리 함수 @@ -21,46 +16,43 @@ function removeToken() { localStorage.removeItem('token'); } -// Axios 인스턴스 생성 함수 -export const createClient = (config?: AxiosRequestConfig): AxiosInstance => { +export const createClient = (config?: AxiosRequestConfig) => { + const token = getToken(); // 토큰 가져오기 const axiosInstance = axios.create({ baseURL: BASE_URL, timeout: DEFAULT_TIMEOUT, headers: { 'Content-Type': 'application/json', + Authorization: token ? `Bearer ${token}` : '', }, withCredentials: true, ...config, }); - // 요청 인터셉터: Authorization 헤더 동적 설정 axiosInstance.interceptors.request.use( (config) => { - const accessToken = getToken(); // 여기서 getToken()을 호출하여 실제로 사용 - if (accessToken) { - if ( - config.headers && - 'set' in config.headers && - typeof (config.headers as AxiosHeaders).set === 'function' - ) { - // AxiosHeaders 타입으로 헤더를 다루는 경우 - (config.headers as AxiosHeaders).set( - 'Authorization', - `Bearer ${accessToken}` - ); - } else { - // 일반 객체로 헤더를 다루는 경우 - config.headers = { - ...config.headers, - Authorization: `Bearer ${accessToken}`, - } as AxiosRequestHeaders; - } + const token = getToken(); + if (token) { + config.headers.Authorization = `Bearer ${token}`; } - console.log('Request Headers:', config.headers); // 디버깅용 로그 return config; }, (error) => { - console.error('Request Error:', error); + return Promise.reject(error); + } + ); + + axiosInstance.interceptors.response.use( + (response) => { + return response; + }, + (error) => { + // 로그인 만료 처리 + if (error.response.status === 401) { + removeToken(); + window.location.href = '/login'; + return; + } return Promise.reject(error); } ); @@ -68,10 +60,36 @@ export const createClient = (config?: AxiosRequestConfig): AxiosInstance => { return axiosInstance; }; -// 기본 Axios 인스턴스 생성 export const httpClient = createClient(); // 토큰 관련 함수 export export { setToken, removeToken, getToken }; -export default httpClient; +// 공통 요청 부분 + +type RequestMethod = 'get' | 'post' | 'put' | 'delete'; + +export const requestHandler = async ( + method: RequestMethod, + url: string, + payload?: T +) => { + let response; + + switch (method) { + case 'post': + response = await httpClient.post(url, payload); + break; + case 'get': + response = await httpClient.get(url); + break; + case 'put': + response = await httpClient.put(url, payload); + break; + case 'delete': + response = await httpClient.delete(url); + break; + } + + return response.data; +}; diff --git a/src/apis/maindata.api.ts b/src/apis/maindata.api.ts index d7ad4c4..63b8e83 100644 --- a/src/apis/maindata.api.ts +++ b/src/apis/maindata.api.ts @@ -1,5 +1,5 @@ -import httpClient from '@/apis/http.api'; -import { mainData } from '@/model/main.model'; +import { httpClient } from './http.api'; +import { mainData } from '@/types/main.model'; export const fetchMainData = async () => { const response = await httpClient.get('/api/main'); @@ -8,4 +8,4 @@ export const fetchMainData = async () => { } catch { throw Error; } -} \ No newline at end of file +}; diff --git a/src/apis/mainpost.api.ts b/src/apis/mainpost.api.ts deleted file mode 100644 index f0b2766..0000000 --- a/src/apis/mainpost.api.ts +++ /dev/null @@ -1,13 +0,0 @@ -import httpClient from '@/apis/http.api'; - -export const fetchPosts = async () => { - try { - console.log('Requesting posts...'); - const response = await httpClient.get('/api/main'); - console.log('Response data:', response.data); - return response.data; - } catch (error) { - console.error('Error fetching posts:', error); - throw error; - } -}; diff --git a/src/assets/DefaultAvatar.svg b/src/assets/DefaultAvatar.svg new file mode 100644 index 0000000..e5daaa3 --- /dev/null +++ b/src/assets/DefaultAvatar.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/AuthButton.tsx b/src/components/AuthButton.tsx deleted file mode 100644 index 305a041..0000000 --- a/src/components/AuthButton.tsx +++ /dev/null @@ -1,95 +0,0 @@ -// src/components/Header.tsx -import { useNavigate } from 'react-router'; -import { useSelector, useDispatch } from 'react-redux'; -import { RootState } from '@/store/rootReducer'; -import { logout } from '@/hooks/userSlice'; -import { removeToken } from '@/apis/http.api'; -import styled from 'styled-components'; - -function AuthButton() { - const navigate = useNavigate(); - const dispatch = useDispatch(); - const isLoggedIn = useSelector((state: RootState) => state.user.isLoggedIn); - - const handleLogin = () => { - // 로그인 페이지로 이동 - navigate('/login'); - }; - - const handleLogout = () => { - // Redux 상태 초기화 - dispatch(logout()); - // 토큰 제거 - removeToken(); - // 로그아웃 후 메인 페이지 이동(필요하다면) - navigate('/'); - }; - - return isLoggedIn ? ( - -
-
-
로그아웃
-
-
-
- ) : ( - -
-
-
로그인
-
-
-
- ); -} - -export default AuthButton; - -// Styled Components 동일 -const ButtonBox = styled.div` - height: 52px; - width: 114px; - - .group { - height: 100%; - position: relative; - } - - .overlap-group { - border-radius: 30px; - display: flex; - align-items: center; - justify-content: center; - height: 100%; - width: 100%; - cursor: pointer; - transition: background-color 0.2s ease-in-out; - } - - .text-wrapper { - color: #ffffff; - font-family: 'Pretendard-ExtraBold', Helvetica; - font-size: 15px; - line-height: 12px; - white-space: nowrap; - } -`; - -const LoginBox = styled(ButtonBox)` - .overlap-group { - background-color: #32c040; - } - .overlap-group:hover { - background-color: #28a034; - } -`; - -const LogoutBox = styled(ButtonBox)` - .overlap-group { - background-color: #9a9a9a; - } - .overlap-group:hover { - background-color: #7f7f7f; - } -`; diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 24ab86c..690cda9 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,21 +1,13 @@ import styled from 'styled-components'; import logo from '@/assets/logo.svg'; -import Avatar from './ui/atoms/Avator'; -import AuthButton from './AuthButton'; +import MenuButton from './MenuButton'; const Header = () => ( Logo -
- -
- +
); diff --git a/src/components/MenuButton.tsx b/src/components/MenuButton.tsx new file mode 100644 index 0000000..e78fe03 --- /dev/null +++ b/src/components/MenuButton.tsx @@ -0,0 +1,146 @@ +import { useState } from 'react'; +import styled from 'styled-components'; +import { XMarkIcon, Bars3Icon } from '@heroicons/react/24/outline'; +import Avatar from './ui/atoms/Avator'; +import defaultAvatar from '@/assets/DefaultAvatar.svg'; +import { useNavigate } from 'react-router'; +import { logout } from '@/hooks/userSlice'; +import { useSelector, useDispatch } from 'react-redux'; +import { RootState } from '@/store/rootReducer'; +import { removeToken } from '@/apis/http.api'; + +const MenuButton = () => { + const [isOpen, setIsOpen] = useState(false); + const navigate = useNavigate(); + const dispatch = useDispatch(); + const isLoggedIn = useSelector((state: RootState) => state.user.isLoggedIn); + + const handleLogin = () => { + // 로그인 페이지로 이동 + navigate('/login'); + }; + + const handleMyPage = () => { + navigate('/mypage'); + }; + + const handleLogout = () => { + // Redux 상태 초기화 + dispatch(logout()); + // 토큰 제거 + removeToken(); + // 로그아웃 후 메인 페이지 이동(필요하다면) + navigate('/'); + }; + + const toggleMenu = () => { + setIsOpen((prev) => !prev); + }; + + const nickname = useSelector( + (state: RootState) => state.user.userInfo?.nickname + ); + + return ( + + {/* 햄버거 버튼 */} + + + {/* 드롭다운 메뉴 */} + {isOpen && ( + +
    +
  • {} : handleLogin}> + {/* 아바타 표시 */} + + + {isLoggedIn ? nickname : '로그인'} + +
  • + {isLoggedIn ? ( + <> +
  • 마이페이지
  • +
  • 문의하기
  • +
  • 서비스 소개
  • +
  • 로그아웃
  • + + ) : ( + <> +
  • 문의하기
  • +
  • 서비스 소개
  • + + )} +
+
+ )} +
+ ); +}; + +export default MenuButton; + +const DropdownContainer = styled.div` + position: relative; +`; + +const Button = styled.button` + background: none; + border: none; + cursor: pointer; + + .icon { + width: 30px; + height: 30px; + color: #333; + } +`; + +const DropdownMenu = styled.div` + position: absolute; + top: 100%; + right: 0; + width: 250px; + background-color: white; + box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); + border: 1px solid #ddd; + z-index: 100; + + ul { + list-style: none; + padding: 10px 0; + margin: 0; + + li { + padding: 10px 15px; + cursor: pointer; + font-weight: bold; + display: flex; + align-items: center; + + &:hover { + background-color: #f3f3f3; + } + } + } +`; + +const AvatarContainer = styled.div` + display: flex; + align-items: center; + gap: 10px; +`; diff --git a/src/components/main-page/MainTagList.tsx b/src/components/main-page/MainTagList.tsx index c69b273..f4dabe0 100644 --- a/src/components/main-page/MainTagList.tsx +++ b/src/components/main-page/MainTagList.tsx @@ -1,45 +1,48 @@ import { useMainTags } from '@/hooks/useMainTags'; import { useSearchParams } from 'react-router'; -import { useState } from 'react'; import styled from 'styled-components'; - const MainTagList = () => { const { maintags } = useMainTags(); const [searchParams, setSearchParams] = useSearchParams(); - const handleTags = (id:number | null) => { + const handleTags = (id: number | null) => { const newSearchParams = new URLSearchParams(searchParams); - if(id === null) { - newSearchParams.delete('id',); + if (id === null) { + newSearchParams.delete('id'); } else { newSearchParams.set('id', id.toString()); } setSearchParams(newSearchParams); - } + }; return ( - { - maintags.map((tag)=>(handleTags(tag.id)}>{tag.name})) - } + {maintags.map((tag) => ( + handleTags(tag.id)} + > + {tag.name} + + ))} ); -} +}; const MainTagListContainer = styled.div` display: flex; justify-content: space-evenly; align-items: center; - `; const TagButton = styled.button` border-radius: 30px; font-size: 1.1rem; background-color: transparent; - color: #32C040; - border: 1px solid #32C040; + color: #32c040; + border: 1px solid #32c040; padding: 8px 20px; text-decoration: none; cursor: pointer; @@ -52,7 +55,6 @@ const TagButton = styled.button` &.active { background-color: rgba(49, 191, 63, 0.23); } - `; -export default MainTagList; \ No newline at end of file +export default MainTagList; diff --git a/src/components/QuestionBox.tsx b/src/components/main-page/QuestionBox.tsx similarity index 70% rename from src/components/QuestionBox.tsx rename to src/components/main-page/QuestionBox.tsx index 69d60d8..664caf0 100644 --- a/src/components/QuestionBox.tsx +++ b/src/components/main-page/QuestionBox.tsx @@ -1,16 +1,17 @@ import { useEffect, useState } from 'react'; import styled from 'styled-components'; -import QuestionBody from './QuestionBody'; -import QuestionHeader from './QuestionHeader'; -import QuestionTag from './QuesitonTag'; -import QuestionBottom from './QuestionBottom'; -import { fetchPosts } from '@/apis/mainpost.api'; -import { PostData } from '@/types/postdata'; +import QuestionBody from '../ui/molecules/mainpage-molecule/QuestionBody'; +import QuestionHeader from '../ui/molecules/mainpage-molecule/QuestionHeader'; +import QuestionTag from '../ui/atoms/mainpage-atom/QuesitonTag'; +import QuestionBottom from '../ui/molecules/mainpage-molecule/QuestionBottom'; +import { fetchMainData } from '@/apis/maindata.api'; +import { mainPosts } from '@/types/main.model'; const QuestionBoxContainer = styled.div` display: flex; flex-direction: column; - gap: 20px; + margin-top: 30px; + gap: 30px; `; const QuestionItem = styled.div` @@ -18,15 +19,15 @@ const QuestionItem = styled.div` `; function QuestionBox() { - const [posts, setPosts] = useState([]); + const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const loadPosts = async () => { try { - const data = await fetchPosts(); - setPosts(data); + const data = await fetchMainData(); + setPosts(data.posts); } catch (err) { setError('데이터를 불러오는 중 오류가 발생했습니다.'); } finally { diff --git a/src/components/ui/atoms/Avator.tsx b/src/components/ui/atoms/Avator.tsx index 4cd4161..2f493a4 100644 --- a/src/components/ui/atoms/Avator.tsx +++ b/src/components/ui/atoms/Avator.tsx @@ -22,8 +22,8 @@ const styles = { height: 200px; `, small: ` - width: 64px; - height: 64px; + width: 48px; + height: 48px; `, disabled: ` opacity: 0.5; diff --git a/src/components/ui/atoms/PasswordGuideLines.tsx b/src/components/ui/atoms/join-atom/PasswordGuideLines.tsx similarity index 100% rename from src/components/ui/atoms/PasswordGuideLines.tsx rename to src/components/ui/atoms/join-atom/PasswordGuideLines.tsx diff --git a/src/components/QuesitonTag.tsx b/src/components/ui/atoms/mainpage-atom/QuesitonTag.tsx similarity index 85% rename from src/components/QuesitonTag.tsx rename to src/components/ui/atoms/mainpage-atom/QuesitonTag.tsx index de55c2a..dcd267e 100644 --- a/src/components/QuesitonTag.tsx +++ b/src/components/ui/atoms/mainpage-atom/QuesitonTag.tsx @@ -11,9 +11,9 @@ const TagsContainer = styled.div` const TagItem = styled.div` background-color: #deffe2; color: #858585; - font-family: 'Pretendard-ExtraLight', Helvetica; - font-size: 8px; - padding: 4px 8px; + font-family: 'Pretendard-Light', Helvetica; + font-size: 12px; + padding: 8px 16px; border-radius: 12px; `; diff --git a/src/components/QuestionButton.tsx b/src/components/ui/atoms/mainpage-atom/QuestionButton.tsx similarity index 88% rename from src/components/QuestionButton.tsx rename to src/components/ui/atoms/mainpage-atom/QuestionButton.tsx index d59f66a..b584ecd 100644 --- a/src/components/QuestionButton.tsx +++ b/src/components/ui/atoms/mainpage-atom/QuestionButton.tsx @@ -14,18 +14,17 @@ const ProblemBox = styled.div` .overlap-group { background-color: #d9d9d9; border-radius: 30px; - height: 20px; + height: 30px; position: relative; - width: 77px; + width: 100px; } .text-wrapper { color: #ffffff; font-family: 'Pretendard-ExtraBold', Helvetica; - font-size: 10px; - height: 13px; - left: 13px; - line-height: 12px; + font-size: 15px; + left: 20px; + line-height: 20px; position: absolute; text-align: center; top: 3px; @@ -48,18 +47,17 @@ const SolveBox = styled.div` .overlap-group { background-color: #c9ffce; border-radius: 30px; - height: 20px; + height: 30px; position: relative; - width: 77px; + width: 100px; } .text-wrapper { color: #007c0c; font-family: 'Pretendard-ExtraBold', Helvetica; - font-size: 10px; - height: 13px; - left: 13px; - line-height: 12px; + font-size: 15px; + left: 25px; + line-height: 20px; position: absolute; text-align: center; top: 4px; diff --git a/src/components/QuestionTitle.tsx b/src/components/ui/atoms/mainpage-atom/QuestionTitle.tsx similarity index 84% rename from src/components/QuestionTitle.tsx rename to src/components/ui/atoms/mainpage-atom/QuestionTitle.tsx index da892d2..0075131 100644 --- a/src/components/QuestionTitle.tsx +++ b/src/components/ui/atoms/mainpage-atom/QuestionTitle.tsx @@ -2,9 +2,10 @@ import styled from 'styled-components'; const TitleContainer = styled.div` font-family: 'Pretendard-SemiBold', Helvetica; - font-size: 10px; + font-size: 18px; color: #000; - margin-left: 8px; + margin-top: 5px; + margin-left: 30px; `; interface TitleProps { diff --git a/src/components/QuestionUser.tsx b/src/components/ui/atoms/mainpage-atom/QuestionUser.tsx similarity index 92% rename from src/components/QuestionUser.tsx rename to src/components/ui/atoms/mainpage-atom/QuestionUser.tsx index 7140476..58cd5f0 100644 --- a/src/components/QuestionUser.tsx +++ b/src/components/ui/atoms/mainpage-atom/QuestionUser.tsx @@ -2,10 +2,11 @@ import styled from 'styled-components'; const UserContainer = styled.div` font-family: 'Pretendard-ExtraLight', Helvetica; - font-size: 10px; + font-size: 12px; color: #666; display: flex; gap: 8px; + margin-left: 5px; `; interface QuestionUserProps { diff --git a/src/components/QuestionUtil.tsx b/src/components/ui/atoms/mainpage-atom/QuestionUtil.tsx similarity index 64% rename from src/components/QuestionUtil.tsx rename to src/components/ui/atoms/mainpage-atom/QuestionUtil.tsx index 3687cfe..f514bc9 100644 --- a/src/components/QuestionUtil.tsx +++ b/src/components/ui/atoms/mainpage-atom/QuestionUtil.tsx @@ -1,19 +1,18 @@ -import { useState } from 'react'; import styled from 'styled-components'; import { ChatBubbleOvalLeftEllipsisIcon, EyeIcon, } from '@heroicons/react/24/outline'; import { HeartIcon as SolidHeartIcon } from '@heroicons/react/24/solid'; -import { HeartIcon as OutlineHeartIcon } from '@heroicons/react/24/outline'; // Styled Components const UtilContainer = styled.div` display: flex; gap: 12px; font-family: 'Pretendard-ExtraLight', Helvetica; - font-size: 10px; + font-size: 13px; color: #666; + margin-right: 5px; `; const IconWrapper = styled.span` @@ -36,23 +35,11 @@ interface QuestionUtilProps { } function QuestionUtil({ likes, comments, views }: QuestionUtilProps) { - const [isLiked, setIsLiked] = useState(false); - const [likeCount, setLikeCount] = useState(likes); - - const toggleLike = () => { - setIsLiked(!isLiked); - setLikeCount((prev) => (isLiked ? prev - 1 : prev + 1)); - }; - return ( - - {isLiked ? ( - - ) : ( - - )} - {likeCount} + + + {likes} diff --git a/src/components/QuestionBody.tsx b/src/components/ui/molecules/mainpage-molecule/QuestionBody.tsx similarity index 70% rename from src/components/QuestionBody.tsx rename to src/components/ui/molecules/mainpage-molecule/QuestionBody.tsx index 9829628..12f73ba 100644 --- a/src/components/QuestionBody.tsx +++ b/src/components/ui/molecules/mainpage-molecule/QuestionBody.tsx @@ -1,11 +1,13 @@ import styled from 'styled-components'; const BodyContainer = styled.div` - font-family: 'Pretendard-ExtraLight', Helvetica; - font-size: 10px; + font-family: 'Pretendard-Light', Helvetica; + font-size: 15px; + margin-left: 5px; line-height: 1.5; color: #333; - margin-top: 8px; + margin-top: 20px; + margin-right: 5px; `; interface QuestionBodyProps { diff --git a/src/components/QuestionBottom.tsx b/src/components/ui/molecules/mainpage-molecule/QuestionBottom.tsx similarity index 82% rename from src/components/QuestionBottom.tsx rename to src/components/ui/molecules/mainpage-molecule/QuestionBottom.tsx index da776ad..810b3e8 100644 --- a/src/components/QuestionBottom.tsx +++ b/src/components/ui/molecules/mainpage-molecule/QuestionBottom.tsx @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import QuestionUser from './QuestionUser'; -import QuestionUtil from './QuestionUtil'; +import QuestionUser from '../../atoms/mainpage-atom/QuestionUser'; +import QuestionUtil from '../../atoms/mainpage-atom/QuestionUtil'; const BottomContainer = styled.div` display: flex; diff --git a/src/components/QuestionHeader.tsx b/src/components/ui/molecules/mainpage-molecule/QuestionHeader.tsx similarity index 75% rename from src/components/QuestionHeader.tsx rename to src/components/ui/molecules/mainpage-molecule/QuestionHeader.tsx index 42675db..28a4110 100644 --- a/src/components/QuestionHeader.tsx +++ b/src/components/ui/molecules/mainpage-molecule/QuestionHeader.tsx @@ -1,6 +1,6 @@ import styled from 'styled-components'; -import QuestionButton from './QuestionButton'; -import QuestionTitle from './QuestionTitle'; +import QuestionButton from '../../atoms/mainpage-atom/QuestionButton'; +import QuestionTitle from '../../atoms/mainpage-atom/QuestionTitle'; const HeaderContainer = styled.div` display: flex; diff --git a/src/hooks/useMainTags.ts b/src/hooks/useMainTags.ts index 2c4b2fe..795a41b 100644 --- a/src/hooks/useMainTags.ts +++ b/src/hooks/useMainTags.ts @@ -1,48 +1,48 @@ import { fetchMainData } from '@/apis/maindata.api'; -import { mainTags } from '@/model/main.model'; +import { mainTags } from '@/types/main.model'; import { useEffect, useState } from 'react'; import { useLocation } from 'react-router'; export const useMainTags = () => { const location = useLocation(); const [maintags, setMaintags] = useState([]); - + const setActive = () => { const params = new URLSearchParams(location.search); - if(params.get('id')) { - setMaintags((prev)=> { + if (params.get('id')) { + setMaintags((prev) => { return prev.map((item) => { - return {...item, isActive: item.id === Number(params.get('id'))} - }) - }) + return { ...item, isActive: item.id === Number(params.get('id')) }; + }); + }); } else { setMaintags((prev) => { return prev.map((item) => { - return {...item, isActive: false} - }) - }) + return { ...item, isActive: false }; + }); + }); } - } + }; - useEffect(()=>{ + useEffect(() => { fetchMainData().then((data) => { - if(!data.tags) return; + if (!data.tags) return; const tagsAll = [ { id: null, name: '전체', }, ...data.tags, - ] + ]; setMaintags(tagsAll); setActive(); - }) + }); }, []); - useEffect(()=>{ + useEffect(() => { setActive(); }, [location.search]); return { maintags }; -} \ No newline at end of file +}; diff --git a/src/hooks/userSlice.ts b/src/hooks/userSlice.ts index 3ce5fd0..4a5b8f4 100644 --- a/src/hooks/userSlice.ts +++ b/src/hooks/userSlice.ts @@ -85,6 +85,10 @@ const userSlice = createSlice({ state.userInfo = userInfo; state.loading = false; state.error = null; + + if (typeof window !== 'undefined') { + localStorage.setItem('token', action.payload); + } }) .addCase(loginAsync.rejected, (state, action) => { state.loading = false; diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 738a3c2..86020db 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,11 +1,15 @@ import MainTagList from '@/components/main-page/MainTagList'; import SearchInput from '@/components/main-page/SearchInput'; +import QuestionBox from '@/components/main-page/QuestionBox'; const HomePage = () => { - return
- - -
; + return ( +
+ + + +
+ ); }; export default HomePage; diff --git a/src/pages/JoinPage.tsx b/src/pages/JoinPage.tsx index 8e540e0..c2c87f0 100644 --- a/src/pages/JoinPage.tsx +++ b/src/pages/JoinPage.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components'; import { useNavigate } from 'react-router'; import qublogo from '@/assets/qublogo.svg'; import { join } from '@/apis/auth.api'; -import PasswordGuideLines from '@/components/ui/atoms/PasswordGuideLines'; +import PasswordGuideLines from '@/components/ui/atoms/join-atom/PasswordGuideLines'; import Input from '@/components/ui/atoms/Input'; export interface JoinProps { diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx index 1f3ba91..f418c29 100644 --- a/src/pages/LoginPage.tsx +++ b/src/pages/LoginPage.tsx @@ -8,7 +8,7 @@ import { RootState } from '@/store/rootReducer'; import { loginAsync } from '@/hooks/userSlice'; import { AppDispatch } from '@/store/store'; -type LoginFormData = { +export type LoginFormData = { email: string; password: string; }; diff --git a/src/model/main.model.ts b/src/types/main.model.ts similarity index 87% rename from src/model/main.model.ts rename to src/types/main.model.ts index fa407cd..c3ae25c 100644 --- a/src/model/main.model.ts +++ b/src/types/main.model.ts @@ -10,16 +10,16 @@ export interface mainPosts { id: number; title: string; content: string; - created_at: string; - updated_at: string; - solved: boolean; + solved: number; nickname: string; + created_at: string; comment_count: number; like_count: number; - tags: string; + view: number; + tags: string | null; } export interface mainData { users: mainUsers; tags: mainTags[]; posts: mainPosts[]; -} \ No newline at end of file +}