Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
dbec029
[feat] ๊ธ€์“ฐ๊ธฐ ๊ธฐ๋Šฅ
EunbinJung Oct 10, 2025
64d9a8e
[feat] ํฌ์ŠคํŠธ ์ž‘์„ฑ ๊ธฐ๋Šฅ
EunbinJung Oct 10, 2025
0692f9d
Merge branch 'dev' into feat/write#19
EunbinJung Oct 10, 2025
c63aa72
Feat/communityscroll#23 (#114)
EunbinJung Oct 10, 2025
b381dc0
[feat] ๊ธ€์“ฐ๊ธฐ ๊ธฐ๋Šฅ
EunbinJung Oct 10, 2025
b1edcc9
์นดํ…Œ๊ณ ๋ฆฌํ•„์ˆ˜
EunbinJung Oct 10, 2025
5cf0cc4
[feat] ํฌ์ŠคํŠธ ๋ฌดํ•œ์Šคํฌ๋กค + ๊ธ€์“ฐ๊ธฐ๊ธฐ๋Šฅ ์ด๋ฏธ์ง€์ถ”๊ฐ€
EunbinJung Oct 10, 2025
37e6b64
[feat] ์ด๋ฏธ์ง€ ์Šค์™€์ดํผ
EunbinJung Oct 11, 2025
0df3876
[feat] ํ”„๋กœํ•„ ์‘ค๋ฆฌ ์ด๋ฏธ์ง€
EunbinJung Oct 11, 2025
c03685b
[feat] ๋Œ“๊ธ€ ๋ˆ„๋ฅด๋ฉด ๋Œ“๊ธ€ ์„น์…˜์œผ๋กœ ๊ฐ€๊ธฐ
EunbinJung Oct 11, 2025
0b9ff6a
[feat] ์ข‹์•„์š”๊ธฐ๋Šฅ(์•„์ง ์ข‹์•„์š”๋ฐ›์•„์˜ค๋Š”๊ฑด ๋ชปํ•จ apiํ•„์š”)
EunbinJung Oct 11, 2025
06f4218
[feat] ๊ฒŒ์‹œ๋ฌผ ์ˆ˜์ •
EunbinJung Oct 11, 2025
41bfd9f
[feat] ๊ธ€ ์ˆ˜์ •
EunbinJung Oct 12, 2025
a9013e6
[refactor] ์ฝ”๋“œ ์กฐ๊ธˆ์ •๋ฆฌ
EunbinJung Oct 12, 2025
7ca7f8b
[feat] ์ž‘์„ฑ์ž๋ณธ์ธ๋งŒ ๊ธ€์ˆ˜์ •์‚ญ์ œ
EunbinJung Oct 12, 2025
d555f39
[feat]๊ธ€ ์‚ญ์ œ๊ธฐ๋Šฅ
EunbinJung Oct 12, 2025
9439bfc
[feat] ์นตํ…Œ์ผํƒœ๊ทธ
EunbinJung Oct 12, 2025
5b72ae4
[fix]์นตํ…Œ์ผ, ์‰์–ด ๊ธฐ๋Šฅ
EunbinJung Oct 12, 2025
5801561
์ˆ˜ ๋ผ์šฐํ„ฐ, ๋น„๋กœ๊ทธ์ธ์ฒ˜๋ฆฌ
EunbinJung Oct 12, 2025
fc5d719
ํƒ€์ž… ์ˆ˜์ •
EunbinJung Oct 12, 2025
18a7eeb
ํƒ€์ž… ์ˆ˜์ •
EunbinJung Oct 12, 2025
9b385db
ํƒ€์ž…์ˆ˜์ •
EunbinJung Oct 12, 2025
379e6e2
ํƒ€์ž…์ˆ˜์ •
EunbinJung Oct 12, 2025
f5a3870
ํƒ€์ž…์ˆ˜์ •
EunbinJung Oct 12, 2025
f1dd851
์˜ค๋ฅ˜์ˆ˜์ •
EunbinJung Oct 12, 2025
1975647
์˜ค๋ฅ˜์ˆ˜์ •
EunbinJung Oct 12, 2025
8beb817
์˜ค๋ฅ˜์ˆ˜์ •
EunbinJung Oct 12, 2025
f811379
์˜ค๋ฅ˜์ˆ˜์ •
EunbinJung Oct 12, 2025
fabb821
์˜ค๋ฅ˜์ˆ˜์ •
EunbinJung Oct 12, 2025
e3f356b
Merge branch 'dev' into feat/write#19
EunbinJung Oct 12, 2025
1cba59c
์ถฉ๋Œํ•ด๊ฒฐ
EunbinJung Oct 12, 2025
2a783d6
์˜ค๋ฅ˜ ์ˆ˜์ •
EunbinJung Oct 12, 2025
641b8e8
์˜ค๋ฅ˜ ์ˆ˜์ •
EunbinJung Oct 12, 2025
d9ffb6f
์˜ค๋ฅ˜ ์ˆ˜์ •
EunbinJung Oct 12, 2025
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
1 change: 1 addition & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { NextConfig } from 'next';
const nextConfig: NextConfig = {

images: {
domains: ['team2-app-s3-bucket.s3.ap-northeast-2.amazonaws.com'],
remotePatterns: [
{
protocol: 'https',
Expand Down
22 changes: 21 additions & 1 deletion package-lock.json

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

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"react": "19.1.0",
"react-dom": "19.1.0",
"react-hot-toast": "^2.6.0",
"react-intersection-observer": "^9.16.0",
"react-use": "^17.6.0"
"react-use": "^17.6.0",
"swiper": "^12.0.2",
"react-intersection-observer": "^9.16.0"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
Expand Down
Binary file removed src.zip
Binary file not shown.
113 changes: 43 additions & 70 deletions src/app/community/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,48 @@
'use client';

import { fetchPostById } from '@/domains/community/api/fetchPost';
import DetailContent from '@/domains/community/detail/DetailContent';
import DetailHeader from '@/domains/community/detail/DetailHeader';
import DetailTitle from '@/domains/community/detail/DetailTitle';
import DetailTabDesktop from '@/domains/community/detail/tab/DetailTabDesktop';
import { Post } from '@/domains/community/types/post';
import Comment from '@/domains/community/detail/Comment';
import StarBg from '@/domains/shared/components/star-bg/StarBg';
import { useParams } from 'next/navigation';
import { useEffect, useState } from 'react';
import DetailSkeleton from '@/domains/community/detail/DetailSkeleton';
import { Metadata } from 'next';
import { getApi } from '@/app/api/config/appConfig';
import DetailPage from '@/domains/community/detail/DetailPage';

type RouteParams = { id: number };

export async function generateMetadata({
params,
}: {
params: Promise<RouteParams>;
}): Promise<Metadata> {
const { id } = await params;
const res = await fetch(`${getApi}/posts/${id}`, {
cache: 'no-store',
});
const post = await res.json();
console.log(post);
return {
title: post.title,
description: post.content?.slice(0, 80),
openGraph: {
title: post.title,
description: post.content?.slice(0, 80),
url: `https://your-domain.com/community/${id}`,
images: [
{
url: post.imageUrls?.[0],
width: 800,
height: 600,
alt: post.title,
},
],
type: 'article',
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.content?.slice(0, 80),
images: [post.imageUrls?.[0]],
},
};
}

function Page() {
const params = useParams();
const [postDetail, setPostDetail] = useState<Post | null>(null);
const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
const postId = params.id;
const fetchData = async () => {
setIsLoading(true);
const data = await fetchPostById(postId);
if (!data) return;

setPostDetail(data);
setIsLoading(false);
};
fetchData();
}, [params.id, setPostDetail]);

if (isLoading) return <DetailSkeleton />;
if (!postDetail) return null;

const {
categoryName,
title,
userNickName,
createdAt,
viewCount,
postId,
tags,
content,
likeCount,
commentCount,
} = postDetail;

return (
<div className="w-full relative">
<StarBg className="w-full h-32 absolute"></StarBg>
<article className="page-layout max-w-824 z-5">
<DetailHeader categoryName={categoryName} />
<DetailTitle title={title} userNickname={userNickName} />
<DetailContent
content={content}
createdAt={createdAt}
viewCount={viewCount}
postId={postId}
tags={tags}
likeCount={likeCount}
commentCount={commentCount}
/>
<section className="mb-10">
<Comment postId={postId} />
</section>
</article>
<div className="hidden md:block">
<DetailTabDesktop likeCount={likeCount} commentCount={commentCount} />
</div>
</div>
);
return <DetailPage />;
}

export default Page;
20 changes: 20 additions & 0 deletions src/app/community/edit/[postId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';

import WriteSection from '@/domains/community/write/WriteSection';
import StarBg from '@/domains/shared/components/star-bg/StarBg';
import { useParams } from 'next/navigation';

function Page() {
const params = useParams();

return (
<div className="w-full mb-20 flex relative">
<StarBg className="w-full h-32 absolute"></StarBg>
<div className="page-layout max-w-824 flex-1 z-5">
<WriteSection mode="edit" postId={params.postId} />
</div>
</div>
);
}

export default Page;
2 changes: 1 addition & 1 deletion src/app/community/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function Page() {
<div className="w-full">
<PageHeader title="Community" description="์นตํ…Œ์ผ์— ๊ด€ํ•œ ๋ชจ๋“  ์ด์•ผ๊ธฐ" />
<div className="page-layout max-w-1024">
<div className="mt-3 mb-10 flex flex-col gap-8 ">
<div className="mt-3 mb-40 flex flex-col gap-8 ">
<section aria-labelledby="community-heading">
<h1 id="community-heading" className="sr-only">
์ปค๋ฎค๋‹ˆํ‹ฐ ํŽ˜์ด์ง€
Expand Down
23 changes: 2 additions & 21 deletions src/app/community/write/page.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,15 @@
'use client';

import Tag from '@/domains/community/components/tag/Tag';
import Category from '@/domains/community/write/Category';
import TagModal from '@/domains/community/write/cocktail-tag/TagModal';
import CompleteBtn from '@/domains/community/write/CompleteBtn';
import FormTitle from '@/domains/community/write/FormTitle';
import ImageSection from '@/domains/community/write/image-upload/ImageSection';
import WriteForm from '@/domains/community/write/WriteForm';
import WriteSection from '@/domains/community/write/WriteSection';
import StarBg from '@/domains/shared/components/star-bg/StarBg';
import { useState } from 'react';

function Page() {
const [isOpen, setIsOpen] = useState(false);

return (
<div className="w-full mb-20 flex relative">
<StarBg className="w-full h-32 absolute"></StarBg>
<div className="page-layout max-w-824 flex-1 z-5">
<CompleteBtn />
<section>
<FormTitle />
<Category />
<WriteForm />
</section>
<ImageSection />
<section className="mt-8">
<Tag use="write" onClick={() => setIsOpen(true)} />
</section>
<WriteSection mode="create" />
</div>
{isOpen && <TagModal isOpen={isOpen} setIsOpen={setIsOpen} />}
</div>
);
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import Header from '@/shared/components/header/Header';
import FooterWrapper from '@/shared/components/footer/FooterWrapper';
import ScrollTopBtnWrapper from '@/shared/components/scroll-top/ScrollTopBtnWrapper';
import KaKaoScript from './api/kakao/KaKaoScript';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import Provider from '@/shared/api/Provider';
import ClientInitHook from '@/domains/login/components/ClientInitHook';

Expand Down
12 changes: 12 additions & 0 deletions src/domains/community/api/fetchCocktails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getApi } from '@/app/api/config/appConfig';

export const fetchCocktails = async () => {
try {
const res = await fetch(`${getApi}/cocktails`);
if (!res.ok) throw new Error('์นตํ…Œ์ผ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์‹คํŒจ');
const data = await res.json();
return data.data;
} catch (error) {
console.error(error);
}
};
9 changes: 5 additions & 4 deletions src/domains/community/api/fetchComment.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { getApi } from '@/app/api/config/appConfig';
import { CommentType } from '../types/post';
import { ParamValue } from 'next/dist/server/request/params';

export const fetchComment = async (postId: number): Promise<CommentType[] | null> => {
export const fetchComment = async (postId: ParamValue | number): Promise<CommentType[] | null> => {
try {
const res = await fetch(`${getApi}/posts/${postId}/comments`, {
method: 'GET',
Expand All @@ -21,7 +22,7 @@ export const fetchComment = async (postId: number): Promise<CommentType[] | null
}
};

export const postComments = async (postId: number, content: string) => {
export const postComments = async (postId: number | ParamValue, content: string) => {
try {
const res = await fetch(`${getApi}/posts/${postId}/comments`, {
method: 'POST',
Expand All @@ -48,7 +49,7 @@ export const postComments = async (postId: number, content: string) => {

export async function updateComment(
accessToken: string | null,
postId: number,
postId: number | ParamValue,
commentId: number,
content: string
): Promise<void> {
Expand All @@ -70,7 +71,7 @@ export async function updateComment(

export async function deleteComment(
accessToken: string | null,
postId: number,
postId: number | ParamValue,
commentId: number
): Promise<void> {
const response = await fetch(`${getApi}/posts/${postId}/comments/${commentId}`, {
Expand Down
10 changes: 9 additions & 1 deletion src/domains/community/api/fetchPost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const fetchPost = async (lastId?: number | null): Promise<Post[] | null>
}
};

export const fetchPostById = async (postId: ParamValue) => {
export const fetchPostById = async (postId: ParamValue | number) => {
try {
const res = await fetch(`${getApi}/posts/${postId}`, {
method: 'GET',
Expand Down Expand Up @@ -87,3 +87,11 @@ export const fetchPostByTab = async ({
return null;
}
};

export async function likePost(postId: number | ParamValue) {
const res = await fetch(`${getApi}/posts/${postId}/like`, {
method: 'POST',
credentials: 'include',
});
if (!res.ok) throw new Error('์ข‹์•„์š” ์‹คํŒจ');
}
10 changes: 8 additions & 2 deletions src/domains/community/components/comment/CommentBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import CommentIcon from '@/shared/assets/icons/comment_28.svg';
import { useState } from 'react';

function CommentBtn({ size }: { size: 'sm' | 'md' }) {
type Props = {
size: 'sm' | 'md';
onClick?: () => void;
};

function CommentBtn({ size, onClick }: Props) {
const [isClick, setIsClick] = useState(false);

const handleClick = () => {
setIsClick(!isClick);
};

return (
<button
type="button"
className={`${size === 'md' ? 'w-13.75 h-13.75 flex-center border-1 border-white rounded-full' : ''} bg-primary`}
aria-label="์ฝ”๋ฉ˜ํŠธ ๋ฒ„ํŠผ"
aria-pressed={isClick}
onClick={handleClick}
onClick={onClick ? onClick : handleClick}
>
<CommentIcon
className="duration-100 hover:[&_*]:fill-tertiary/50 [&_*]:duration-200"
Expand Down
15 changes: 9 additions & 6 deletions src/domains/community/components/like/LikeBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import LikeIcon from '@/shared/assets/icons/like_28.svg';
import { useState } from 'react';

function LikeBtn({ size }: { size: 'sm' | 'md' }) {
const [isClick, setIsClick] = useState(false);
type Props = {
size: 'sm' | 'md';
onClick?: () => void;
isClick?: boolean; // ์™ธ๋ถ€์—์„œ ์ œ์–ด
};

const handleClick = () => {
setIsClick(!isClick);
};
function LikeBtn({ size, onClick, isClick = false }: Props) {
return (
<button
type="button"
className={`${size === 'md' ? 'w-13.75 h-13.75 flex-center border-1 border-white rounded-full' : ''} bg-primary`}
aria-label="์ข‹์•„์š” ๋ฒ„ํŠผ"
aria-pressed={isClick}
onClick={handleClick}
onClick={() => {
if (onClick) onClick();
}}
>
<LikeIcon
fill={`${isClick ? '#81689d' : 'transparent'}`}
Expand Down
2 changes: 1 addition & 1 deletion src/domains/community/components/post-info/PostInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function PostInfo({
<li aria-hidden="true">|</li>
<li>์กฐํšŒ {viewCount || 0}</li>
<li aria-hidden="true">|</li>
<li>๋Œ“๊ธ€ {commentCount + 1 || 0}</li>
<li>๋Œ“๊ธ€ {commentCount || 0}</li>
</ul>
);
}
Expand Down
Loading