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

[FEAT] 프로젝트 상세조회 페이지 구현 #73

Merged
merged 6 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
6 changes: 6 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@mantine/hooks": "^7.11.2",
"@mantine/styles": "^6.0.22",
"@tabler/icons-react": "^3.11.0",
"classnames": "^2.5.1",
"next": "14.2.4",
"react": "^18",
"react-dom": "^18"
Expand Down
Binary file added public/images/_mock/project-poster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/_mock/project-thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/app/(user)/projects/[id]/page.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.container {
width: 98%;
border: 1px solid #efeff0; /* TODO: dark mode 세팅 추가*/
background-color: var(--color-background);
margin: 10px auto;
border-radius: 12px;

padding: 10px 20px;
}
20 changes: 18 additions & 2 deletions src/app/(user)/projects/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
export default function ProjectDetailPage() {
return <main>Hello, world!</main>;
import { ProjectDetailInfo, ProjectDetailComment } from "@/components/pages/ProjectDetail";
import classes from "./page.module.css";
import { ProjectDetailInquiry } from "@/components/pages/ProjectDetail/ProjectDetailInquiry";

interface Props {
params: {
id: string;
};
}

export default function ProjectDetailPage({ params: { id } }: Props) {
return (
<div className={classes.container}>
<ProjectDetailInfo projectId={id} />
<ProjectDetailComment projectId={id} />
<ProjectDetailInquiry />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Usage: Story = {
args: {
label: "Button",
children: "Button",
},
};

export const Disabled: Story = {
args: {
label: "Button",
children: "Button",
disabled: true,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "@testing-library/jest-dom";

describe("PrimaryButton component", () => {
it("renders correctly with the given label", () => {
render(<PrimaryButton label="Button" />);
render(<PrimaryButton>Button</PrimaryButton>);
// More on screen queries: https://testing-library.com/docs/queries/about
// More on jest expect Api: https://jestjs.io/docs/expect
expect(screen.getByRole("button", { name: "Button" })).toBeInTheDocument();
Expand Down
15 changes: 9 additions & 6 deletions src/components/common/Buttons/PrimaryButton/PrimaryButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Button, ButtonProps } from "@mantine/core";
import classNames from "classnames";
import classes from "./PrimaryButton.module.css";

export function PrimaryButton({ label, ...props }: ButtonProps & { label?: string }) {
export function PrimaryButton({
children,
className,
...props
}: ButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>) {
return (
<>
<Button className={classes.element} {...props}>
{label}
</Button>
</>
<Button className={classNames(classes.element, className)} {...props}>
{children}
</Button>
);
}
2 changes: 1 addition & 1 deletion src/components/common/CommentBox/CommentBox.module.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("src/theme/fonts/pretendard.css");
@import url("@/theme/fonts/pretendard.css");

.commentBoxContainer {
display: flex;
Expand Down
7 changes: 4 additions & 3 deletions src/components/common/CommentBox/CommentBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import classes from "./CommentBox.module.css";

interface CommentBoxProps {
onSubmit?: (comment: string) => void;
commentList?: Comment[];
}

interface Comment {
export interface Comment {
author: string;
content: string;
}

export const CommentBox: React.FC<CommentBoxProps> = ({ onSubmit }) => {
export const CommentBox: React.FC<CommentBoxProps> = ({ onSubmit, commentList = [] }) => {
const [comment, setComment] = useState("");
const [comments, setComments] = useState<Comment[]>([]);
const [comments, setComments] = useState<Comment[]>(commentList);

const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setComment(e.target.value);
Expand Down
Empty file removed src/components/pages/.gitkeep
Empty file.
30 changes: 30 additions & 0 deletions src/components/pages/ProjectDetail/ProjectDetailComment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use client";

import { useEffect, useState } from "react";
import { CommentBox, Comment } from "@/components/common/CommentBox/CommentBox";
import { comments as commentList } from "./_mock/mock-project";

interface Props {
projectId: string;
}

export function ProjectDetailComment({ projectId }: Props) {
const [comments, setComments] = useState<Comment[]>(commentList);

useEffect(() => {
/**
* TODO: 댓글 목록 불러오기
*/
console.log("projectId: ", projectId);
}, [projectId]);

const handleCommentSubmit = (comment: string) => {
/**
* TODO: 댓글 등록하기
*/
const newComment = { author: "사람", content: comment };
setComments([...comments, newComment]);
};

return <CommentBox commentList={comments} onSubmit={handleCommentSubmit} />;
}
115 changes: 115 additions & 0 deletions src/components/pages/ProjectDetail/ProjectDetailInfo.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
.title {
font-size: 32px;
line-height: 40px;
font-weight: 700;
padding: 10px 0px;
}

.description {
font-size: 20px;
line-height: 25px;
}

.sectionMiddle {
margin-top: 40px;
margin-bottom: 15px;
gap: 80px;

@media (max-width: 768px) {
flex-direction: column;
gap: 40px;
}
}

.imageWrapper {
position: relative;
width: 100%;
height: auto;
max-width: 635px;
aspect-ratio: 635 / 350; /* 이미지 비율 설정 */
}

.infoContainer {
width: 100%;
padding-right: 40px;

@media (max-width: 768px) {
flex-direction: column;
padding-right: 0px;
}
}

.infoContainer > .infoRowGroup {
width: 100%;
}

.infoContainer > .infoRowGroup > .infoRow {
display: flex;
gap: 10px;
width: 100%;
line-height: 22px;
font-size: 16px;
}

.infoRow > .firstCol {
font-weight: 700;
width: 72px;
flex-shrink: 0; /* 다른 item이 영역 침범하지 않도록 함 */
}

.divider {
width: 100%;
}

.btnLabel {
padding-left: 5px;
font-size: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.addBtn {
width: 45%;
height: 56px;
}

.externalBtn {
width: 40%;
height: 60px;
background-color: var(--color-primaryFixedDim);
color: #000000;

font-size: 20px;

&:hover {
background-color: #d1e4ff;
color: #000000;
}

@media (max-width: 768px) {
width: 80%;
}
}

.sectionBottom {
margin-top: 40px;
}

.posterWrapper {
width: 100%;
max-width: 794px;
}

/* ProjectDetailInquiry 컴포넌트에서 사용 */

.SectionInquiry {
margin-top: 50px;
margin-bottom: 30px;
}

.SectionInquiry > button {
font-size: 20px;
height: 56px;
margin-top: 20px;
}
Loading
Loading