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

[강대원] sprint9 #129

Merged
Merged
Show file tree
Hide file tree
Changes from 9 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
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": ["next/core-web-vitals", "next/typescript"]
"extends": ["next/core-web-vitals", "next/typescript"],
"rules": {
"@typescript-eslint/no-explicit-any": "off"
}
}
36 changes: 36 additions & 0 deletions app/ClientLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client";

import { usePathname } from "next/navigation";
import Nav from "@/components/common/nav/Nav";
import Footer from "@/components/common/footer/Footer";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

// 숨길 페이지를 객체로 관리
const hiddenRoutes = {
login: "/login",
signup: "/signin",
};

const queryClient = new QueryClient();

export default function ClientLayout({
children,
}: {
children: React.ReactNode;
}) {
const pathname = usePathname();
// 현재 경로가 숨길 페이지에 포함되는지 확인
const hideNavAndFooter = Object.values(hiddenRoutes).includes(pathname);

return (
<QueryClientProvider client={queryClient}>
<div className="flex min-h-screen flex-col pt-[75px]">
{!hideNavAndFooter && <Nav />}
<main className="flex-grow">{children}</main>
{!hideNavAndFooter && <Footer />}
</div>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
5 changes: 5 additions & 0 deletions app/articles/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const ArticleDetailPage = () => {
return <div>page</div>;
};

export default ArticleDetailPage;
5 changes: 5 additions & 0 deletions app/articles/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const ArticleCreatePage = () => {
return <div>page</div>;
};

export default ArticleCreatePage;
15 changes: 15 additions & 0 deletions app/articles/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import AllArticles from "@/components/articles/AllArticles";
import BestArticles from "@/components/articles/BestArticles";

const ArticlePage = () => {
return (
<article className="p-4 md:p-6">
<div className="mx-auto min-w-[325px] max-w-[1200px]">
<BestArticles />
<AllArticles />
</div>
</article>
);
};

export default ArticlePage;
3 changes: 3 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
@tailwind utilities;

:root {
--red: #f74747;
--pink: #ff68cc;

--blue: #3692ff;
--blue-text: #ffffff;

Expand Down
41 changes: 41 additions & 0 deletions app/items/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use client";

import LoadingSpinner from "@/components/common/loading/LoadingSpinner";
import ProductForm from "@/components/items/ProductForm";
import { getProduct } from "@/services/productApi";
import { ProductCreateRequest } from "@/types/products";
import { useQuery } from "@tanstack/react-query";

const ProductUpdatePage = ({ params }: { params: { id: string } }) => {
const productId = Number(params.id);

const { data: product, isLoading } = useQuery({
queryKey: ["product", productId],
queryFn: () => getProduct(productId),
});

console.log(product);

if (isLoading) return <LoadingSpinner />;
if (!product) return <div>상품을 찾을 수 없습니다.</div>;

const productData: ProductCreateRequest = {
name: product.name,
description: product.description,
price: product.price,
tags: product.tags,
images: product.images,
};

return (
<section className="mx-auto box-border max-w-[1200px] px-6 pb-40 pt-6">
<ProductForm
defaultValues={productData}
productId={productId}
isEdit={true}
/>
</section>
);
};

export default ProductUpdatePage;
58 changes: 58 additions & 0 deletions app/items/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"use client";

import ConfirmDeleteModal from "@/components/common/modal/ConfirmDeleteModal";
import ProductInfoSection from "@/components/items/ProductInfoSection";
import { deleteProduct } from "@/services/productApi";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useRouter } from "next/navigation";
import { useState } from "react";

const ProductDetailPage = ({ params }: { params: { id: string } }) => {
const { id: productId } = params;

const router = useRouter();
const queryClient = useQueryClient();

const deleteMutation = useMutation({
mutationFn: () => deleteProduct(Number(productId)),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["products"] });
router.push("/items");
},
});

const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);

const handleOpenDeleteModal = () => {
setIsDeleteModalOpen(true);
};

const handleCloseDeleteModal = () => {
console.log("close");
setIsDeleteModalOpen(false);
};

return (
<article className="px-4 pt-4 sm:px-6 sm:pt-6">
<ProductInfoSection
productId={productId}
onOpenDeleteModal={handleOpenDeleteModal}
/>
{isDeleteModalOpen && (
<ConfirmDeleteModal
message="정말로 상품을 삭제하시겠어요?"
leftBtnText="취소"
rightBtnText="네"
type="red"
onClose={handleCloseDeleteModal}
onConfirm={() => {
deleteMutation.mutate(); // 실제 삭제 API 호출
handleCloseDeleteModal(); // 모달 닫기
}}
/>
)}
</article>
);
};

export default ProductDetailPage;
11 changes: 11 additions & 0 deletions app/items/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import ProductForm from "@/components/items/ProductForm";

const ProductCreatePage = () => {
return (
<section className="mx-auto box-border max-w-[1200px] px-6 pb-40 pt-6">
<ProductForm />
</section>
);
};

export default ProductCreatePage;
16 changes: 16 additions & 0 deletions app/items/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import AllProducts from "@/components/items/AllProducts";
import BestProducts from "@/components/items/BestProducts";
import React from "react";

const ItemsPage = () => {
return (
<article className="px-6 py-7">
<section className="mx-auto flex max-w-[1200px] flex-col gap-10">
<BestProducts />
<AllProducts />
</section>
</article>
);
};

export default ItemsPage;
11 changes: 5 additions & 6 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import Nav from "@/components/common/nav/Nav";
import Footer from "@/components/common/footer/Footer";
import ClientLayout from "./ClientLayout";

const pretendard = localFont({
src: "./fonts/PretendardVariable.woff2",
Expand All @@ -14,6 +13,9 @@ const pretendard = localFont({
export const metadata: Metadata = {
title: "판다 마켓",
description: "Generated by 대원",
icons: {
icon: "/icons/favicon/favicon.ico",
},
};

export default function RootLayout({
Expand All @@ -26,10 +28,7 @@ export default function RootLayout({
<html lang="ko" className={`${pretendard.variable} antialiased`}>
<body className={pretendard.className}>
<div className="flex min-h-screen flex-col">
<Nav />
<main className="flex-grow p-4 md:p-6">{children}</main>

<Footer />
<ClientLayout>{children}</ClientLayout>
</div>
</body>
</html>
Expand Down
23 changes: 23 additions & 0 deletions app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import AuthLogo from "@/components/auth/AuthLogo";
import AuthLoginForm from "@/components/auth/AuthLoginForm";
import SnsLogin from "@/components/auth/SnsLogin";
import AuthSigninPrompt from "@/components/auth/AuthSignupPrompt";
import ErrorModal from "@/components/common/modal/ErrorModal";

const LoginPage = () => {
return (
<article className="px-4">
<section className="relative mx-auto flex h-screen max-w-[640px] flex-col items-center justify-center gap-6">
<AuthLogo />
<AuthLoginForm />
<SnsLogin />
<AuthSigninPrompt />
<ErrorModal />
</section>
</article>
);
};

export default LoginPage;
6 changes: 1 addition & 5 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import BackButton from "@/components/common/button/BackButton";
import Link from "next/link";
import React from "react";

const NotFound = () => {
return (
<div className="mt-40 flex h-full flex-col items-center justify-center gap-10">
<div className="h-full text-center text-3xl font-bold">
404-Page not found
</div>
<Link href={"/"}>
<BackButton>홈으로 돌아가기</BackButton>
</Link>
<BackButton backPath="/">홈으로 돌아가기</BackButton>
</div>
);
};
Expand Down
33 changes: 17 additions & 16 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
"use client";
import HomeBanner from "@/components/home/HomeBanner";
import topBannerImage from "@/public/images/home/hero-image.png";
import bottomBannerImage from "@/public/images/home/bottom-banner-image.png";

import BestPost from "@/components/post/BestPost/BestPost";
import PostList from "@/components/post/PostList/PostList";
import { useRouter } from "next/navigation";
import { useEffect } from "react";

export default function Home() {
const router = useRouter();

useEffect(() => {
router.replace("/post");
}, [router]);
export default function HomePage() {
return (
<article className="mx-auto min-w-[325px] max-w-[1200px]">
<BestPost />
<PostList />
</article>
<>
<HomeBanner
title="일상의 모든 물건을 거래해 보세요"
buttonText="구경하러 가기"
buttonLink="/login"
imageSrc={topBannerImage}
/>
<HomeBanner
title="믿을 수 있는 <br /> 판다마켓 중고 거래"
imageSrc={bottomBannerImage}
isFooter
/>
</>
);
}
1 change: 1 addition & 0 deletions app/post/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";

const PostEditPage = () => {
return <PostEditor />;
// return <div>PostEditPage</div>;
};

export default PostEditPage;
22 changes: 12 additions & 10 deletions app/post/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
"use client";

import Link from "next/link";

import BackButton from "@/components/common/button/BackButton";
import CommentInput from "@/components/post/PostDetail/CommentInput";
import CommentList from "@/components/post/PostDetail/CommentList";
import CommentInput from "@/components/common/comment/CommentInput";
import CommentList from "@/components/common/comment/CommentList";
import PostDetailContent from "@/components/post/PostDetail/PostDetailContent";

const PostDetailPage = () => {
const PostDetailPage = ({ params }: { params: { id: string } }) => {
const { id: productId } = params;

return (
<article className="mx-auto max-w-[1200px]">
{/* 게시글 내용 */}
<PostDetailContent />

{/* 댓글달기 */}
<CommentInput />
<CommentInput
title="댓글달기"
placeholder="댓글을 입력해주세요."
productId={productId}
/>

{/* 댓글창 */}
<CommentList />
<CommentList id={productId} />

{/* 돌아가기 버튼 */}
<Link href="/post">
<BackButton> 목록으로 돌아가기</BackButton>
</Link>
<BackButton backPath="/post"> 목록으로 돌아가기</BackButton>
</article>
);
};
Expand Down
8 changes: 5 additions & 3 deletions app/post/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import PostList from "@/components/post/PostList/PostList";

const PostPage = () => {
return (
<article className="mx-auto min-w-[325px] max-w-[1200px]">
<BestPost />
<PostList />
<article className="p-4 md:p-6">
<div className="mx-auto min-w-[325px] max-w-[1200px]">
<BestPost />
<PostList />
</div>
</article>
);
};
Expand Down
Loading