-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[김세환] sprint10 #304
The head ref may contain hidden characters: "Next-\uAE40\uC138\uD658-sprint10"
[김세환] sprint10 #304
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{ | ||
"cSpell.words": ["sortmobile"] | ||
"cSpell.words": ["addboard", "addfile", "sortmobile"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import axios from "@/lib/axios"; | ||
|
||
interface Params<T> { | ||
data: T; | ||
token: string; | ||
} | ||
|
||
export const postNewArticle = async ({ data, token }: Params<object>) => { | ||
const res = await axios.post("/articles", data, { | ||
headers: { Authorization: `Bearer ${token}` }, | ||
}); | ||
}; | ||
|
||
export const postUploadImage = async ({ data, token }: Params<File>) => { | ||
const formData = new FormData(); | ||
formData.append("image", data); | ||
try { | ||
const res = await axios.post("/images/upload", formData, { | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}); | ||
return res.data; | ||
} catch (err) { | ||
console.log(err); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
import axios from "@/lib/axios"; | ||
import { ArticleQuery } from "@/models/article"; | ||
import { ArticleResponse } from "@/models/article"; | ||
import { | ||
Article, | ||
ArticleQuery, | ||
CommentResponse, | ||
GetCommentParam, | ||
} from "@/types/article"; | ||
import { ArticleResponse } from "@/types/article"; | ||
|
||
export const getArticleList = async ({ | ||
page = 1, | ||
|
@@ -16,3 +21,23 @@ export const getArticleList = async ({ | |
const { list, totalCount }: ArticleResponse = res.data; | ||
return { list, totalCount }; | ||
}; | ||
|
||
export const getArticlesById = async (articleId: number) => { | ||
const res = await axios.get(`/articles/${articleId}`); | ||
const { data }: { data: Article } = res; | ||
return data; | ||
}; | ||
|
||
export const getArticleComment = async ({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p4; |
||
articleId, | ||
limit = 5, | ||
cursor, | ||
}: GetCommentParam) => { | ||
const res = await axios.get( | ||
`/articles/${articleId}/comments?limit=${limit}${ | ||
cursor ? `&cursor=${cursor}` : "" | ||
}` | ||
); | ||
const { data }: { data: CommentResponse } = res; | ||
return data; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import axios from "@/lib/axios"; | ||
|
||
interface PostArticleCommentParams { | ||
articleId: number; | ||
data: string; | ||
token: string; | ||
} | ||
|
||
export const postArticleComment = async ({ | ||
articleId, | ||
data, | ||
token, | ||
}: PostArticleCommentParams) => { | ||
try { | ||
const body = { | ||
content: data, | ||
}; | ||
const res = await axios.post(`/articles/${articleId}/comments`, body, { | ||
headers: { Authorization: `Bearer ${token}` }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p3; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ex) const instance = axios.create({
baseURL: 'https://panda-market-api.vercel.app',
});
instance.interceptors.request.use((config) => {
const token = localStorage.getItem('accessToken');
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
});
export default instance;
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그리고 jwt 토큰에는 일반적으로 만료기한이 설정되어 있습니다. 따라서, 로컬스토리지에 저장되어 있는 accessToken의 값을 디코딩하여, 예를들어 Jwt의 유효 시간을 확인하는 방식은 아래와 같습니다. // jwt 디코딩
const decodeToken = (token) => {
const payload = token.split('.')[1];
const decodedPayload = atob(payload);
return JSON.parse(decodedPayload);
}
// 토큰의 유효 시간 확인 함수
const isTokenExpired = (token) => {
const decoded = decodeToken(token);
const currentTime = Math.floor(Date.now() / 1000);
return decoded.exp < currentTime; // exp가 현재 시간보다 이전이면 토큰 만료
} |
||
}); | ||
} catch (err) { | ||
console.log(err); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import axios from "@/lib/axios"; | ||
import { access } from "fs"; | ||
|
||
interface AuthData { | ||
email: string; | ||
password: string; | ||
} | ||
|
||
interface ResponseData { | ||
accessToken: string; | ||
refreshToken: string; | ||
} | ||
|
||
export const postSignIn = async (authData: AuthData) => { | ||
const res = await axios.post("/auth/signIn", authData); | ||
const { accessToken, refreshToken }: ResponseData = res.data; | ||
return { accessToken, refreshToken }; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import Button from "@/components/ui/Button"; | ||
import FileInput from "@/components/ui/FileInput"; | ||
import Input from "@/components/ui/Input"; | ||
import TextArea from "@/components/ui/TextArea"; | ||
import useAddBoard from "@/hooks/useAddBoard"; | ||
|
||
export default function AddBoardForm() { | ||
const { | ||
inputValues, | ||
onChangeInput, | ||
onSubmitForm, | ||
onChangeFileInput, | ||
isInputValid, | ||
} = useAddBoard(); | ||
return ( | ||
<form className="m-container mt-[70px] pt-4"> | ||
<div className="flex justify-between"> | ||
<span className="font-bold text-xl">게시글 쓰기</span> | ||
<Button | ||
className="btn w-[74px] h-[42px]" | ||
onClick={onSubmitForm} | ||
activeBtn={isInputValid} | ||
> | ||
등록 | ||
</Button> | ||
</div> | ||
<Input | ||
name="title" | ||
placeholder="제목을 입력해주세요" | ||
type="input" | ||
label="*제목" | ||
value={inputValues.title} | ||
onChange={onChangeInput} | ||
/> | ||
<TextArea | ||
name="content" | ||
placeholder="내용을 입력해 주세요" | ||
label="*내용" | ||
value={inputValues.content} | ||
onChange={onChangeInput} | ||
/> | ||
<FileInput | ||
value="" | ||
onChange={onChangeFileInput} | ||
name="image" | ||
label="이미지" | ||
image={inputValues.image} | ||
/> | ||
</form> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p4;
단일 아티클을 fetching하는 것이므로 getArticleById와 같이 단수형을 사용해도 좋을 것 같아요!