Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 64 additions & 9 deletions package-lock.json

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

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.4.0",
"styled-components": "^6.1.16"
"styled-components": "^6.1.16",
"typescript": "^5.8.3"
},
"devDependencies": {
"@eslint/js": "^9.21.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.1",
"@types/styled-components": "^5.1.34",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.21.0",
"eslint-plugin-react-hooks": "^5.1.0",
Expand Down
22 changes: 16 additions & 6 deletions src/App.jsx → src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { ThemeProvider } from 'styled-components'
import { theme } from './styles/theme'
import GlobalStyles from './styles/GlobalStyles'
import { Routes, Route, BrowserRouter } from 'react-router-dom'

import Home from './pages/Home/Home'
import Login from './pages/LoginAndSignup/Login'
import Signup from './pages/LoginAndSignup/Signup'
import Items from './pages/Items/Items'
import ItemsDetail from './pages/ItemsDetail/ItemsDetail'
import AddItem from './pages/AddItem/AddItem'
import Privacy from './pages/Privacy/privacy’'
import Faq from './pages/Faq/Faq'
import NavVArLayout from './Layout/NavVArLayout'

import { ThemeProvider } from 'styled-components'
import { theme } from './styles/theme'
import GlobalStyles from './styles/GlobalStyles'

function App() {
return (
Expand All @@ -18,9 +23,14 @@ function App() {
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/items" element={<Items />} />
<Route path="/items/:productId" element={<ItemsDetail />} />
<Route path="/additem" element={<AddItem />} />
<Route path="/privacy" element={<Privacy />} />
<Route path="/faq" element={<Faq />} />

<Route element={<NavVArLayout />}>
<Route path="/items" element={<Items />} />
<Route path="/items/:productId" element={<ItemsDetail />} />
<Route path="/additem" element={<AddItem />} />
</Route>
</Routes>
</BrowserRouter>
</ThemeProvider>
Expand Down
19 changes: 19 additions & 0 deletions src/Layout/NavVArLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Outlet, useLocation } from 'react-router-dom'
import ItemsNavVar from '../component/common/ItemsNavVar'

const NavVArLayout = () => {
const { pathname } = useLocation() // 현재 페이지가 어떤 페이지인지 감지

const isItemsPage = pathname === '/additem' || pathname.startsWith('/items')
const isBoardsPage = pathname === '/boards'

return (
<>
<ItemsNavVar isItemsPage={isItemsPage} isBoardsPage={isBoardsPage} />
<Outlet />
{/*Outlet을 통해 하위 라우트 렌더링함. App 컴포넌트에서 확인 가능 */}
</>
)
}

export default NavVArLayout
8 changes: 0 additions & 8 deletions src/api/client/interceptors.jsx

This file was deleted.

25 changes: 25 additions & 0 deletions src/api/client/interceptors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AxiosRequestConfig } from 'axios'

export const requestInterceptor = (
config: AxiosRequestConfig
): AxiosRequestConfig => {
const token: string | null = localStorage.getItem('token')

if (token) {
config.headers = config.headers || {}
config.headers['Authorization'] = `Basic ${token}`
}
return config
}

// 전 코드
// import { AxiosRequestConfig } from 'axios'

// export const requestInterceptor = (config: AxiosRequestConfig) => {
// const { token } = localStorage.getItem('token') ?? ''

// if (token) {
// config.headers.set('Authorization', `Basic${token}`)
// }
// return config
// }
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import requestor from '../client/requestor'

import { Comment } from '../../types/comment'
import { Axios, AxiosResponse } from 'axios'

class CommentService {
// 틀릴 수도
postProductComment(productId, body) {
Expand All @@ -10,7 +13,11 @@ class CommentService {
return requestor.post(`/products/${productId}/comments`, requestBody)
}

getProductComment(productId, limit, cursor) {
getProductComment(
productId: number,
limit: number,
cursor?: number
): Promise<AxiosResponse<Comment>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 하셔도 됩니다만, 라이브러리를 쓰실 때 해당 라이브러리에서 제공해주는 타입이 어떤지 살펴보고 활용해 보시는 것도 좋습니다.

예를 들면 axios의 경우 get 메서드에 제네릭을 제공합니다!
image

따라서 requestor.get 제네릭에 Comment를 넘겨주면 getProductComment의 리턴 타입은 자동으로 잡히게 되는거죠~!

getProductComment(productId: number, limit: number, cursor?: number) {
    let url = `/products/${productId}/comments?limit=${limit}`

    if (cursor) {
      url += `&cursor=${cursor}`
    }

    return requestor.get<Comment>(url)
  }

라이브러리의 타입은 알트(맥은 커맨드) + 클릭으로 확인하실 수 있습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저 스크린샷이 공포스럽게 느껴질 수도 있을 거 같아 추가로 말씀드리면, 처음엔 눈에 안 들어오는 것이 너무 당연합니다!
꼭 저렇게 찾아 들어가지 않고 다른 사람이 사용한 코드를 참고하셔도 좋습니다! 조금씩 쓰고, 보다 보면 익숙해 지실거에요 :)

let url = `/products/${productId}/comments?limit=${limit}`

if (cursor) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { Axios, AxiosResponse } from 'axios'
import requestor from '../client/requestor'
import { GetProductIdTypes } from '../../types/product'

class ProductService {
//틀릴 수도
postProduct(body) {
postProduct(body: GetProductIdTypes) {
const requestBody = {
...body,
}
return requestor.post(`/products`, requestBody)
}

getProduct(page, pageSize, orderBy, keyword) {
getProduct(page: number, pageSize: number, orderBy: string, keyword: string) {
return requestor.get(
`/products?page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`
)
}

getProductId(productId) {
getProductId(productId: number): Promise<AxiosResponse<GetProductIdTypes>> {
return requestor.get(`/products/${productId}`)
}

Expand Down
25 changes: 25 additions & 0 deletions src/assets/images.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
declare module '*.png' {
const value: string
export default value
}

declare module '*.jpg' {
const value: string
export default value
}

declare module '*.jpeg' {
const value: string
export default value
}

declare module '*.gif' {
const value: string
export default value
}

declare module '*.svg' {
const value: string
export default value
}
// 문자열로 타입선언하는 이유는 <img src="경로"> 이기 때문
Loading
Loading