diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2c96871..fc0c387 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,97 +5,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - + + + { @@ -139,7 +60,7 @@ "ModuleVcsDetector.initialDetectionPerformed": "true", "RunOnceActivity.ShowReadmeOnStart": "true", "RunOnceActivity.git.unshallow": "true", - "git-widget-placeholder": "fillincode", + "git-widget-placeholder": "release-0.2", "js.debugger.nextJs.config.created.client": "true", "js.debugger.nextJs.config.created.server": "true", "last_opened_file_path": "C:/Users/pkpk0/WebstormProjects/ddip/public/fonts", @@ -160,11 +81,11 @@ + - @@ -199,7 +120,14 @@ - + + + + + + + + @@ -211,7 +139,19 @@ - + + + diff --git a/jsconfig.json b/jsconfig.json index e954206..1bcbd37 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -2,6 +2,7 @@ "compilerOptions": { "baseUrl": "src", "paths": { + "@/*": ["*"], "@home/*": ["app/feature/home/*"], "@constants/*": ["constants/*"], "@auth/*": ["app/feature/auth/*"], diff --git a/public/Write.png b/public/Write.png new file mode 100644 index 0000000..3590643 Binary files /dev/null and b/public/Write.png differ diff --git a/public/chat-back.svg b/public/chat-back.svg new file mode 100644 index 0000000..9c3cdf0 --- /dev/null +++ b/public/chat-back.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/chat-send.svg b/public/chat-send.svg new file mode 100644 index 0000000..7c06bc2 --- /dev/null +++ b/public/chat-send.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/chat.png b/public/chat.png new file mode 100644 index 0000000..859d21f Binary files /dev/null and b/public/chat.png differ diff --git a/src/app/api/route.js b/src/app/api/route.js index 0f96f7d..233fca9 100644 --- a/src/app/api/route.js +++ b/src/app/api/route.js @@ -1,14 +1,24 @@ -import clientPromise from '@/lib/mongodb' -import { NextResponse } from 'next/server' +import clientPromise from '@/lib/mongodb'; export async function GET() { try { - const client = await clientPromise - const db = client.db('ddip') // .env의 DB 이름과 동일하게 - const posts = await db.collection('posts').find({}).toArray() - return NextResponse.json(posts) + const client = await clientPromise; + const db = client.db('ddip'); // ddip DB 선택 + const collection = db.collection('object'); // object 컬렉션 선택 + const data = await collection.find({}).toArray(); + + return new Response(JSON.stringify(data), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); } catch (error) { - console.error(error) - return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }) + console.error('MongoDB 조회 에러:', error); + return new Response( + JSON.stringify({ message: '서버 에러 발생' }), + { + status: 500, + headers: { 'Content-Type': 'application/json' }, + } + ); } } diff --git a/src/app/components/chat/chat-component.js b/src/app/components/chat/chat-component.js new file mode 100644 index 0000000..0f91bb3 --- /dev/null +++ b/src/app/components/chat/chat-component.js @@ -0,0 +1,23 @@ +import Image from "next/image"; + +export default function ChatMessage({ chatId, name, lastUser, lastMessage, time, profileImg, onClick }) { + return ( +
+ {/* 프로필 이미지 */} +
+ profile +
+ + {/* 채팅 내용 */} +
+
+

{name}

+ {time} +
+

{lastUser}: {lastMessage}

+
+ +
+ ); +} diff --git a/src/app/components/chat/chat-list.js b/src/app/components/chat/chat-list.js new file mode 100644 index 0000000..ed8d6c3 --- /dev/null +++ b/src/app/components/chat/chat-list.js @@ -0,0 +1,62 @@ +import { useState } from "react"; +import ChatMessage from "./chat-component"; +import Chatting from "./chatting"; + +export default function ChatList() { + const chatData = [ + { + chatId: "1", //채팅에 고유번호를 부여해야하는 걸까요? + name: "고구마 한박스", //상품명 + lastUser: '고구미', + lastMessage: "고구마 10개 사고 싶습니다!", + time: "13:45", + profileImg: "/none" //해당 상품 1번째 사진으로 + }, + { + chatId: "2", + name: "감자 10kg", + lastUser: '감자군', + lastMessage: "언제 만날까요?", + time: "12:20", + profileImg: "/none" + } + ]; + + const [selectedChat, setSelectedChat] = useState(null); + + const handleCloseChat = () => { + setSelectedChat(null); + } + + return (<> +
+ {/* 상단 */} +
+

메세지

+
+ + {/* 채팅 목록 */} +
+ {chatData.map(chat => ( + setSelectedChat(chat)} + /> + ))} +
+
+ + {/* 선택된 채팅창 모달 띄우기 */} + {selectedChat && ( + + )} + + ); +} diff --git a/src/app/components/chat/chatting.js b/src/app/components/chat/chatting.js new file mode 100644 index 0000000..bd5b6b4 --- /dev/null +++ b/src/app/components/chat/chatting.js @@ -0,0 +1,117 @@ +// chatting.js +import {useState, useEffect, useRef} from "react"; +import Image from "next/image"; + +export default function Chatting({chatId, name, profileImg, onClose}) { + const [messages, setMessages] = useState([]); + const [input, setInput] = useState(""); + const messagesEndRef = useRef(null); //스크롤 위치 제일 아래로 + + //리엑트에서 컴포넌트가 화면에 처음 나타나는 순간(컴포넌트 마운트)에 로컬스토리지에서 불러오기 + useEffect(() => { + const stored = localStorage.getItem(`chatMessages-${chatId}`); + if (stored) setMessages(JSON.parse(stored)); + }, [chatId]); + + //메세지 보내기 + const handleSend = () => { + if (input.trim() === "") return; + + //본인 (보내는 사람) -> 로그인&회원가입에서 받은 정보를 바탕으로 수정 + const newMessage = { + id: Date.now(), + text: input, + sender: "me", + name: "나", //별명 + time: new Date().toLocaleTimeString([], {hour: "2-digit", minute: "2-digit"}) + }; + + const updatedMessages = [...messages, newMessage]; + + //예시 메세지 (보낸 사람) -> 로그인&회원가입에서 받은 정보를 바탕으로 수정 + const autoReply = { + id: Date.now() + 1, + text: "고구마 10개 사고 싶습니다!", + sender: "other", //상대 메세지 + name: "고구미", + time: new Date().toLocaleTimeString([], {hour: "2-digit", minute: "2-digit"}) + }; + + const finalMessages = [...messages, newMessage, autoReply]; + + setMessages(finalMessages); + localStorage.setItem(`chatMessages-${chatId}`, JSON.stringify(finalMessages)); + setInput(""); + }; + + //messages가 변경될 때마다 스크롤을 밑으로 이동 + useEffect(() => { + if (messagesEndRef.current) { + messagesEndRef.current.scrollIntoView({behavior: "smooth"}); + } + }, [messages]); + + + return ( +
+ {/* 상단 */} +
+ +

{name}

+
+ + {/* 채팅 부분 */} +
+ {messages.map((msg) => ( +
+ +
+ {/* 이름 (상대방 메시지일 때만 표시) */} + {msg.sender !== "me" && ( + + {msg.name} + + )} + {/* 말풍선 + 시간*/} +
+ {/* 말풍선 */} + + {msg.text} + + {/* 시간 */} + + {msg.time} + +
+
+
+ ))} + {/* 스크롤 제일 밑에 위치한 빈 div */} +
+
+ + {/* 입력 부분 */} +
+ setInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleSend()} + className="flex-1 px-2 text-sm focus:outline-none" + placeholder="메시지를 입력하세요." + /> + +
+
+ ); +} diff --git a/src/app/components/common/post.js b/src/app/components/common/post.js new file mode 100644 index 0000000..31b1243 --- /dev/null +++ b/src/app/components/common/post.js @@ -0,0 +1,71 @@ +import { useState } from "react"; +import Image from "next/image"; +import category_lists from "@constants/simpleDB"; + +export default function PostBox({ onClose }) { + const [activeTags, setActiveTags] = useState([]); + + const handleClick = (value) => { + setActiveTags((prev) => + prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value] + ); + }; + + return ( +
+ {/* 상단 */} +
+ +

게시글

+
+ + {/* 제목 */} +
+ + +
+ + {/* 이미지 첨부 */} +
+ +
+
+
+ +
+
+ + {/* 본문 입력 */} +
+