From 542400928165d453886d757fc2dd6b9e39aafe2a Mon Sep 17 00:00:00 2001 From: "DESKTOP-FLTTDHD\\dmhs4" Date: Mon, 20 Jan 2025 22:20:09 +0900 Subject: [PATCH 01/68] temp --- .../community/[communityId]/modify/page.tsx | 3 +- app/(pages)/community/[communityId]/page.tsx | 3 +- app/(pages)/community/page.tsx | 5 +- app/(pages)/community/post/page.tsx | 5 +- app/components/button.tsx | 5 +- .../community/communityComponents.tsx | 65 +++++++++++++++---- app/components/community/postComponents.tsx | 2 +- package-lock.json | 11 ++++ package.json | 1 + 9 files changed, 78 insertions(+), 22 deletions(-) diff --git a/app/(pages)/community/[communityId]/modify/page.tsx b/app/(pages)/community/[communityId]/modify/page.tsx index 955b173..e881b04 100644 --- a/app/(pages)/community/[communityId]/modify/page.tsx +++ b/app/(pages)/community/[communityId]/modify/page.tsx @@ -136,7 +136,8 @@ export default function BoardDetail() { <> + { router.back(); }}> diff --git a/app/(pages)/community/[communityId]/page.tsx b/app/(pages)/community/[communityId]/page.tsx index 7dca86f..bcd8667 100644 --- a/app/(pages)/community/[communityId]/page.tsx +++ b/app/(pages)/community/[communityId]/page.tsx @@ -149,7 +149,8 @@ export default function BoardDetail() { <>
+ leftButton={ { location.href = '/community' }}> diff --git a/app/(pages)/community/page.tsx b/app/(pages)/community/page.tsx index f151154..270ca41 100644 --- a/app/(pages)/community/page.tsx +++ b/app/(pages)/community/page.tsx @@ -16,7 +16,10 @@ export default function BoardMain() { return ( <> Community} + leftButton={ { location.href = '/community' }} + >Community} rightButton={ diff --git a/app/(pages)/community/post/page.tsx b/app/(pages)/community/post/page.tsx index 765ecdc..fc6c7f0 100644 --- a/app/(pages)/community/post/page.tsx +++ b/app/(pages)/community/post/page.tsx @@ -82,7 +82,8 @@ export default function Post() { <> + {location.href='/community'; }} > @@ -102,7 +103,7 @@ export default function Post() { } />
- +
diff --git a/app/components/button.tsx b/app/components/button.tsx index 4a20ff8..28b85b8 100644 --- a/app/components/button.tsx +++ b/app/components/button.tsx @@ -120,11 +120,12 @@ export function SearchButtonForNav() { type TextLogoButtonForNavProps = { children: string; className?: string; + onclick?: () => void; } -export function TextLogoButtonForNav({ children, className }: TextLogoButtonForNavProps) { +export function TextLogoButtonForNav({ children, className, onclick }: TextLogoButtonForNavProps) { return ( -
)} @@ -145,17 +143,11 @@ function InfoPageContent() {
-
)} diff --git a/app/(pages)/keyword/layout.tsx b/app/(pages)/keyword/layout.tsx index 1ef8695..26658bc 100644 --- a/app/(pages)/keyword/layout.tsx +++ b/app/(pages)/keyword/layout.tsx @@ -2,49 +2,38 @@ import type { Metadata } from "next"; import "@/app/globals.css"; import TopNav from "@/app/components/TopNav"; import { ReactNode } from "react"; -import { SearchButtonForNav, TextButtonForNav } from "@/app/components/button"; - - +import { SearchButtonForNav } from "@/app/components/button"; +import TextButtonForNavWrapper from "@/app/components/TextButtonForNavWrapper"; export const metadata: Metadata = { - title: "MukPic-Keyword", - description: "MukPic Keyword Page", + title: "MukPic-Keyword", + description: "MukPic Keyword Page", }; -//기본 레이아웃 +// 기본 레이아웃 /* 구조 - body[main{div class="root-container"(header,본문,footer)}] 일단 스타일 설정은 body 와 main은 비워두고 root-container에만 해놓았음 */ type LayoutProps = { - children: ReactNode; + children: ReactNode; }; - export default function Layout({ children }: LayoutProps) { - return ( - - /* 메인 */ -
- - - } - rightButton={ - - - } - >Post} - /> -
- {/* 상단 내비게이션 필요한 버튼 넣어서 사용용 */} - {/* 메인 페이지 내용 */} - {children} - {/* 하단 네비게이션 */} -
-
- ); + return ( + /* 메인 */ +
+ } + rightButton={} + /> +
+ {/* 상단 내비게이션 필요한 버튼 넣어서 사용 */} + {/* 메인 페이지 내용 */} + {children} + {/* 하단 네비게이션 */} +
+
+ ); } diff --git a/app/(pages)/keyword/page.tsx b/app/(pages)/keyword/page.tsx index e5042c8..3a04615 100644 --- a/app/(pages)/keyword/page.tsx +++ b/app/(pages)/keyword/page.tsx @@ -144,7 +144,7 @@ function KeywordPageContent() {
- ) - + + ); } type ViewAiResearchButtonProps = { icon?: ReactNode; diff --git a/package-lock.json b/package-lock.json index 2d9abae..2dd6917 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@types/classnames": "^2.3.0", "axios": "^1.7.9", + "date-fns": "^4.1.0", "js-cookie": "^3.0.5", "next": "^15.1.4", "react": "^18.3.1", @@ -2110,6 +2111,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", diff --git a/package.json b/package.json index 8b1fe00..5a71acc 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "dependencies": { "@types/classnames": "^2.3.0", "axios": "^1.7.9", + "date-fns": "^4.1.0", "js-cookie": "^3.0.5", "next": "^15.1.4", "react": "^18.3.1", From 818c321bd352838625e6729c9e34d9d620dfb5de Mon Sep 17 00:00:00 2001 From: "DESKTOP-FLTTDHD\\dmhs4" Date: Wed, 22 Jan 2025 21:59:48 +0900 Subject: [PATCH 05/68] =?UTF-8?q?feat=20:=20community=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94=20=EB=B0=8F=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20?= =?UTF-8?q?=EB=93=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #3 --- app/(css)/community.css | 46 +++- .../community/[communityId]/modify/page.tsx | 131 +++++---- app/(pages)/community/[communityId]/page.tsx | 48 +++- app/(pages)/community/page.tsx | 36 +-- app/(pages)/community/post/page.tsx | 6 +- .../community/communityComponents.tsx | 257 ++++++++++++++---- app/components/community/postComponents.tsx | 107 +++++++- app/types/postStore.ts | 42 ++- 8 files changed, 511 insertions(+), 162 deletions(-) diff --git a/app/(css)/community.css b/app/(css)/community.css index 1a9aa09..b64c29b 100644 --- a/app/(css)/community.css +++ b/app/(css)/community.css @@ -47,7 +47,7 @@ flex-direction: column; height: 100%; background-color: white; - padding : 0.75rem 3% 1.12rem 3%; + padding: 0.75rem 3% 1.12rem 3%; } .post-profile-wrapper { @@ -95,6 +95,22 @@ img { background: #0a0c10; box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.1); } +.view-ai-research-button-carousel { + display: flex; + width: 9.3125rem; + height: 2.25rem; + padding: 0.625rem 0.5rem 0.625rem 0.75rem; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0.5rem; + position: absolute; + left: 0.75rem; + bottom: 2.25rem; + border-radius: 6.1875rem; + background: #0a0c10; + box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.1); +} .view-ai-research-button-text { display: inline-flex; @@ -289,9 +305,10 @@ img { } .food-category-dropdown-list { - max-width: 6.375rem; - width: 100%; - max-height: 15.625rem; + position: absolute; + max-width: 10rem; + z-index: 25; + max-height: 17rem; overflow-y: auto; border-radius: 1rem 1rem 1rem 1rem; border-top: 0.5px solid #000; @@ -301,10 +318,13 @@ img { } .food-category-dropdown-item { + overflow-y: auto; + z-index: 25; display: flex; align-items: center; /* 세로 방향 가운데 정렬 */ justify-content: flex-start; /* 가로 방향 왼쪽 정렬 */ - padding-left: 1.53rem; + padding-left: 1rem; + padding-right: 1rem; width: 100%; height: 2.25rem; border-bottom: 0.5px solid #000; @@ -430,4 +450,20 @@ textarea { line-height: 1.375rem; /* 137.5% */ letter-spacing: -0.01875rem; min-height: 9.625rem; + white-space: normal; /* 텍스트 줄바꿈 활성화 */ + word-wrap: break-word; /* 단어가 길 경우 줄바꿈 */ + overflow-wrap: break-word; /* 긴 단어가 넘치지 않도록 처리 */ + word-break: break-word; /* 긴 단어를 끊어 줄바꿈 */ +} + +.category-scroll-container { + width: 100%; /* 부모 요소의 가로 크기 */ + overflow-x: auto; /* 가로 스크롤을 가능하게 */ + white-space: nowrap; /* 자식 요소들이 가로로 나열되도록 설정 */ +} + +/* 버튼들 - 기본적으로 가로로 나열될 수 있도록 설정 */ +.category-scroll-container button { + display: inline-block; /* 버튼들이 가로로 나열되도록 */ + margin-right: 10px; /* 버튼들 간의 간격 */ } diff --git a/app/(pages)/community/[communityId]/modify/page.tsx b/app/(pages)/community/[communityId]/modify/page.tsx index e881b04..e57d207 100644 --- a/app/(pages)/community/[communityId]/modify/page.tsx +++ b/app/(pages)/community/[communityId]/modify/page.tsx @@ -1,6 +1,6 @@ 'use client'; import { SvgButtonForNav } from "@/app/components/button"; -import { Write } from "@/app/components/community/postComponents"; +import { Modify, Write } from "@/app/components/community/postComponents"; import TopNav from "@/app/components/TopNav"; import { usePostStore } from "@/app/types/postStore"; import axios from "axios"; @@ -29,12 +29,14 @@ export default function BoardDetail() { const content = usePostStore(state => state.content); const images = usePostStore(state => state.images); const category = usePostStore(state => state.category); - const imageUrl = usePostStore(state => state.imageUrl); + const imageUrls = usePostStore(state => state.imageUrls); const setTitle = usePostStore(state => state.setTitle); const setContent = usePostStore(state => state.setContent); // const setImages = usePostStore(state => state.setImages); const setCategory = usePostStore(state => state.setCategory); - const setImageUrl = usePostStore(state => state.setImageUrl); + const setImageUrls = usePostStore(state => state.setImageUrls); + const likeCount = usePostStore(state => state.likeCount); + const setLikeCount = usePostStore(state => state.setLikeCount); // 타입 정의 @@ -52,41 +54,63 @@ export default function BoardDetail() { // 수정 버튼 클릭 시 function UpDateHandler() { - if (title && content && images && category) { - // 이미지 등록 - axios({ - method: 'post', - url: `${process.env.NEXT_PUBLIC_ROOT_API}/images/upload`, - data: { - file: images, - type: 'COMMUNITY' - } - }).then((response) => { - axios({ - method: 'patch', - url: `${process.env.NEXT_PUBLIC_ROOT_API}/community/${communityId}`, - data: { - communityKey: communityId, - title: title, - content: content, - // 필요하면 카테고리 추가 - imageUrls: [...imageUrl, ...response.data], - likecount: post?.likeCount - }, - headers: { - Authorization: `${localStorage.getItem('Authorization')}` - } - }).then((response) => { - if (response.status === 200) { - alert('Item successfully modified.'); - router.push(`/community/${communityId}`); - } - }).catch((error) => { - console.error('게시글 수정 api 에러: ', error); - }) - }).catch((error) => { - console.error('게시글 이미지 등록 api 에러: ', error); - }) + if (title && content && category) { + if (images.length > 0) { + const uploadPromises = images.map((image) => { + const uploadFormData = new FormData(); + uploadFormData.append("file", image); + uploadFormData.append("type", 'COMMUNITY'); + + return axios({ + method: 'post', + url: `${process.env.NEXT_PUBLIC_ROOT_API}/images/upload`, + data: uploadFormData + }).then((response) => { + const imageUrl = response.data[0]; + return imageUrl; // 서버에서 반환한 이미지 URL 배열 + }); + }); + Promise.all(uploadPromises) + .then((uploadedImageUrlsArrays) => { + // uploadedImageUrlsArrays는 배열 안에 배열이 있을 수 있으므로, 이를 평평하게(flatten) 만듭니다 + const flattenedImageUrls = [].concat(...uploadedImageUrlsArrays); + console.log('업로드된 이미지 URLs:', flattenedImageUrls); + let uploadedImageUrls: string[] = []; + + if (imageUrls.length > 0) { + uploadedImageUrls = [...flattenedImageUrls, ...imageUrls]; // 기존 imageUrls와 결합 + } else { + uploadedImageUrls = flattenedImageUrls; // 단독으로 flattenedImageUrls만 사용 + } + console.log('업로드된 이미지 URLs:', imageUrls); + console.log('업로드된 이미지 URLs:', uploadedImageUrls); + + + // 게시글 등록 API 호출 + axios({ + method: 'patch', + url: `${process.env.NEXT_PUBLIC_ROOT_API}/community/${communityId}`, + data: { + communityKey: communityId, + title: title, + content: content, + imageUrls: uploadedImageUrls, + likecount: likeCount + }, + headers: { + Authorization: `${localStorage.getItem('Authorization')}` + } + }).then((response) => { + if (response.status === 200) { + alert('Item successfully modified.'); + router.push(`/community/${communityId}`); + } + }).catch((error) => { + console.error('게시글 수정 api 에러: ', error); + }) + }) + + } } } @@ -98,24 +122,25 @@ export default function BoardDetail() { if (communityId) { console.log('use effect 작동 체크 communityId: ', communityId); axios.get(`${process.env.NEXT_PUBLIC_ROOT_API}/community/${communityId}`, - { - headers: - { + { + headers: + { Authorization: `${localStorage.getItem('Authorization')}` - } + } } ) .then((response) => { - if(response.status === 200) { - setPost(response.data); - // 정보 불러오면서 상태 업데이트 - setTitle(response.data.title); - setContent(response.data.content); - setImageUrl(response.data.imageUrls); - setCategory(''); // 카테고리 정보는 없음 - setLoading(false); + if (response.status === 200) { + setPost(response.data); + // 정보 불러오면서 상태 업데이트 + setTitle(response.data.title); + setContent(response.data.content); + setImageUrls(response.data.imageUrls); + setCategory(''); // 카테고리 정보는 없음 + setLikeCount(response.data.likeCount); + setLoading(false); } - if(response.status === 401) { + if (response.status === 401) { alert('You do not have permission to view this.'); router.push('/community'); } @@ -127,7 +152,7 @@ export default function BoardDetail() { }); } - }, [communityId, setTitle, setCategory, setContent, setImageUrl, router]); // communityId가 변경될 때마다 호출 + }, [communityId, setTitle, setCategory, setContent, setImageUrls, setLikeCount, router]); // communityId가 변경될 때마다 호출 // 로딩 상태와 에러 처리 if (loading) return
Loading...
; @@ -157,7 +182,7 @@ export default function BoardDetail() { } />
- +
diff --git a/app/(pages)/community/[communityId]/page.tsx b/app/(pages)/community/[communityId]/page.tsx index bcd8667..9fe271a 100644 --- a/app/(pages)/community/[communityId]/page.tsx +++ b/app/(pages)/community/[communityId]/page.tsx @@ -14,6 +14,11 @@ export default function BoardDetail() { const router = useRouter(); const pathname = usePathname() as string; const [communityId, setCommunityId] = useState(null); + const [currentIndex, setCurrentIndex] = useState(0); + const [imageUrls, setImageUrls] = useState([]); + + + const DropdownForNav = () => { const [isOpen, setIsOpen] = useState(false); @@ -45,7 +50,7 @@ export default function BoardDetail() { {isOpen && ( -
+