Skip to content

Commit

Permalink
feat : 이미지 모달창 생성
Browse files Browse the repository at this point in the history
  • Loading branch information
han-wo98 committed Jun 14, 2024
1 parent 3d1084f commit 5d3e8c6
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 13 deletions.
9 changes: 6 additions & 3 deletions app/boards/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BoardDetail from "@/components/BoardDetail/BoardDetail";
import CommentInput from "@/components/BoardDetail/CommentInput";
import CommentsList from "@/components/BoardDetail/CommentsList";
import { getComments } from "@/app/apis/getComments";
import { getArticleDetail, RootObject } from "@/app/apis/getArticleDetail";
import styles from "@/app/boards/[id]/Page.module.css";
import backIcon from "@/app/assets/images/ic_back.png";
import Link from "next/link";
Expand All @@ -13,16 +14,18 @@ interface BoardDetailProps {
};
}

export default function BoardDetailPage({ params }: BoardDetailProps) {
export default async function BoardDetailPage({ params }: BoardDetailProps) {
const articleId = parseInt(params.id, 10);
const { list: comments } = await getComments(articleId, 5);
const article: RootObject = await getArticleDetail(articleId);

return (
<div>
<div className={styles.boardDetail}>
<BoardDetail articleId={articleId} />
<BoardDetail article={article} />
<label className={styles.commentLabel}>댓글달기</label>
<CommentInput articleId={articleId} />
<CommentsList articleId={articleId} />
<CommentsList articleId={articleId} comments={comments} />
<div className={styles.commentButtonContainer}>
<Link href="/boards">
<button className={styles.backButton}>
Expand Down
27 changes: 22 additions & 5 deletions components/BoardDetail/BoardDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
"use client";
import styles from "@/components/BoardDetail/BoardDetail.module.css";
import { getArticleDetail, RootObject } from "@/app/apis/getArticleDetail";
import { RootObject } from "@/app/apis/getArticleDetail";
import { formatDate } from "@/app/utils/formateDate";
import Image from "next/image";
import profileImg from "@/app/assets/images/ic_profile.png";
import LikeButton from "./LikeButton";
import DropdownMenu from "@/components/DropDown";
import { useState } from "react";
import ImageModal from "@/components/ImageModal";

type Props = {
articleId: number;
article: RootObject;
};

export default async function BoardDetail({ articleId }: Props) {
const article: RootObject = await getArticleDetail(articleId);
export default function BoardDetail({ article }: Props) {
const [isModalOpen, setIsModalOpen] = useState(false);

const openModal = () => {
setIsModalOpen(true);
};

const closeModal = () => {
setIsModalOpen(false);
};

return (
<div className={styles.container}>
<div className={styles.titleContainer}>
<div className={styles.titleWrapper}>
<div className={styles.title}>{article.title}</div>
<DropdownMenu articleId={articleId} />
<DropdownMenu articleId={article.id} />
</div>
<div className={styles.tagWrapper}>
<div className={styles.writerInfo}>
Expand All @@ -42,10 +53,16 @@ export default async function BoardDetail({ articleId }: Props) {
className={styles.image}
width={72}
height={72}
onClick={openModal}
/>
)}
</div>
</div>
<ImageModal
isOpen={isModalOpen}
onClose={closeModal}
imageSrc={article.image || ""}
/>
</div>
);
}
8 changes: 3 additions & 5 deletions components/BoardDetail/CommentsList.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import styles from "@/components/BoardDetail/CommentList.module.css";
import { getComments } from "@/app/apis/getComments";
import emptyCommentImg from "@/app/assets/images/Img_reply_empty.png";
import { formatTimes } from "@/app/utils/fotmatTime";
import DropdownMenu from "@/components/DropDown";
import ProfileImg from "@/app/assets/images/ic_profile.png";
import Image from "next/image";

import { List } from "@/app/apis/getComments";
interface Props {
articleId: number;
comments: List[];
}

export default async function CommentDetail({ articleId }: Props) {
const { list: comments } = await getComments(articleId, 5);

export default function CommentsList({ articleId, comments }: Props) {
return (
<div className={styles.commentsCard}>
{comments && comments.length > 0 ? (
Expand Down
54 changes: 54 additions & 0 deletions components/ImageModal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.modalOverlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.modal {
position: relative;
max-width: 90%;
max-height: 90%;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.modalContent {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: #000;
}

.closeButton {
position: absolute;
top: 16px;
right: 16px;
border: none;
border-radius: 50%;
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color: #333;
cursor: pointer;
transition: background-color 0.3s ease;
}

.closeButton:hover {
background-color: rgba(255, 255, 255, 1);
}
37 changes: 37 additions & 0 deletions components/ImageModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useRef } from "react";
import styles from "./ImageModal.module.css";
import Image from "next/image";
import useOutsideClick from "@/app/hooks/useOutsideClick";

type Props = {
isOpen: boolean;
onClose: () => void;
imageSrc: string;
};

export default function ImageModal({ isOpen, onClose, imageSrc }: Props) {
const modalRef = useRef<HTMLDivElement>(null);

useOutsideClick(modalRef, onClose);

if (!isOpen) return null;

return (
<div className={styles.modalOverlay}>
<div className={styles.modal} ref={modalRef}>
<div className={styles.modalContent}>
<Image
src={imageSrc}
alt="Article Image"
objectFit="contain"
width={700}
height={700}
/>
<button className={styles.closeButton} onClick={onClose}>
X
</button>
</div>
</div>
</div>
);
}

0 comments on commit 5d3e8c6

Please sign in to comment.