Skip to content
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

Next 정진호 sprint8 #57

Open
wants to merge 6 commits into
base: next-정진호
Choose a base branch
from
Open
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
27 changes: 0 additions & 27 deletions .github/pull-request-template.md

This file was deleted.

31 changes: 0 additions & 31 deletions .github/workflows/auto-label-assign.yml

This file was deleted.

43 changes: 43 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

80 changes: 80 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import axios from "axios";

const baseURL = "https://four-sprint-mission-be.onrender.com";

const client = axios.create({
baseURL,
});

const getProducts = async ({
page = 1,
pageSize = 10,
orderBy = "recent",
keyword = "",
} = {}) => {
const url = `/products?page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`;
const response = await client.get(url);
const data = response.data;
Copy link
Collaborator

Choose a reason for hiding this comment

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

이런건 그냥 간결하게 return response.data 로 빼도 될것 같아요~


return data;
};

const getArticles = async ({
limit = 10,
sort = "latest",
skip = 0,
keyword = "",
} = {}) => {
const params = { limit, sort, skip, keyword };
const url = `/articles?`;
const res = await client.get(url, { params });

return res.data.articles;
};

const getArticle = async (articleId) => {
const url = `/articles/${articleId}`;
const response = await client.get(url);
const data = response.data;

return data;
};

const postArticle = async (articleData) => {
const url = `/articles`;
const response = await client.post(url, articleData);
return response.data;
};

// 게시글 삭제
const deleteArticle = async (articleId) => {
const url = `/articles/${articleId}`;
const res = await client.delete(url);
return res.data;
};

const editArticle = async (articleId, newArticle) => {
const url = `/articles/${articleId}`;
const res = await client.patch(url, newArticle);
return res.data;
};

const getCommentsOfArticle = async ({ articleId, limit = 10, cursor = 0 }) => {
const url = `/articles/${articleId}/commets?limit=${limit}&cursor=${cursor}`;
const response = await client.get(url);
const data = response.data;

return data;
};

const api = {
getProducts,
getArticles,
getArticle,
getCommentsOfArticle,
postArticle,
deleteArticle,
editArticle,
};

export default api;
14 changes: 14 additions & 0 deletions app/(providers)/(root)/_components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";

function Footer() {
return (
<footer className="flex justify-evenly items-center h-32 bg-blue-950 text-white">
<p>codeit - 2025</p>
<p>Privacy Policy</p>
<p>FAQ</p>
<p>instagram</p>
</footer>
);
}

export default Footer;
31 changes: 31 additions & 0 deletions app/(providers)/(root)/_components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import Link from "next/link";
import React from "react";
import Image from "next/image";
import Logo from "@/assets/img/logo.png";
import Button from "@/components/Button";

function Header() {
return (
<header className="h-20 px-36 flex items-center justify-between border-b-2">
{/* 로고 */}
<Link href="/">
<Image alt="logo" src={Logo} className="w-[140px] h-auto" />
</Link>
<ol className="flex flex-1 px-10 justify-start gap-x-10 font-medium">
<Link href="/articles">
<li>자유게시판</li>
</Link>
<Link href="/market">
<li>중고마켓</li>
</Link>
</ol>

{/* 로그인 버트 */}
<div>
<Button>로그인</Button>
</div>
</header>
);
}

export default Header;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Button from "@/components/Button";
import React from "react";

function ArticleComments() {
return (
<div>
<form className="flex flex-col gap-4">
<label htmlFor="content" className="text-base font-semibold">
댓글 달기
</label>
<textarea
id="content"
placeholder="댓글을 입력해주세요."
className="bg-gray-200 px-6 py-4 rounded-lg"
/>
<Button>등록</Button>
</form>
<div>
<p>사용 기간이 어떻게 되실까요?</p>
<Button>수정하기</Button>
<Button>삭제하기</Button>
<p>똑똑한 판다</p>
<p>1시간 전</p>
</div>
</div>
);
}

export default ArticleComments;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use client";

import api from "@/api";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useRouter } from "next/navigation";

function DeleteArticleButton({ children, articleId }) {
const router = useRouter();
const { mutate: deleteArticle } = useMutation({
mutationFn: () => api.deleteArticle(articleId),
onSuccess: () => {
router.replace("/articles");
},
});

const handClick = () => {
deleteArticle();
};

return (
<button className="cursor-pointer" onClick={handClick}>
{children}
</button>
);
}

export default DeleteArticleButton;
70 changes: 70 additions & 0 deletions app/(providers)/(root)/articles/[articleId]/edit/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"use client";

import api from "@/api";
import Button from "@/components/Button";
import Input from "@/components/Input";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useParams, useRouter } from "next/navigation";
import { useEffect, useState } from "react";

function ArticleEditPage() {
const router = useRouter();
const params = useParams();
const articleId = params.articleId;
const [title, setTitle] = useState("");
const [content, setContent] = useState("");

const { data: article } = useQuery({
queryFn: () => api.getArticle(articleId),
queryKey: ["articles"],
});

useEffect(() => {
if (article) {
setTitle(article.title || "");
setContent(article.content || "");
}
}, [article]);

const { mutate: editArticle } = useMutation({
mutationFn: (newArticle) => api.editArticle(articleId, newArticle),
onSuccess: () => {
router.push(`/articles/${articleId}`);
},
});

const handleSubmit = (e) => {
e.preventDefault();
const newArticle = { title, content };
editArticle(newArticle);
};

return (
<main className="flex flex-col gap-5 max-w-7xl m-auto my-8">
<form onSubmit={handleSubmit}>
<div className="flex justify-between items-center mb-6">
<h2 className="text-xl font-bold">게시글 수정</h2>
<Button>수정</Button>
</div>
<Input
type="text"
label="*제목"
name="title"
placeholder="제목을 입력해주세요."
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<Input
type="textarea"
label="*내용"
name="content"
placeholder="내용을 입력해주세요."
value={content}
onChange={(e) => setContent(e.target.value)}
/>
</form>
</main>
);
}

export default ArticleEditPage;
Loading