Skip to content

Commit

Permalink
feat: 메세지리스트 컴포넌트의 자동 스크롤 기능 추가 & api 연결 테스트
Browse files Browse the repository at this point in the history
  • Loading branch information
gogumalatte committed Nov 2, 2024
1 parent 88acb88 commit 7633328
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 39 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_BASE_URL=http://13.238.194.87:3001
13 changes: 13 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import axios from "axios";

// VITE_BASE_URL로 변경하여 환경 변수 가져오기
const baseURL = import.meta.env.VITE_BASE_URL;

const apiClient = axios.create({
baseURL,
headers: {
"Content-Type": "application/json",
},
});

export default apiClient;
17 changes: 11 additions & 6 deletions src/pages/main/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ const MainPage = () => {
const [messages, setMessages] = useState<string[]>([]);
const [inputMessage, setInputMessage] = useState("");
const [isSidebarOpen, setSidebarOpen] = useState(true);
const [isLoggedIn, setIsLoggedIn] = useState(false); // 로그인 상태 추가
const [userInfo, setUserInfo] = useState({ name: "", email: "" }); // 사용자 정보 상태 추가
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userInfo, setUserInfo] = useState({ name: "", email: "" });

useEffect(() => {
const kakaoToken = localStorage.getItem("kakaoToken");
if (kakaoToken) {
setIsLoggedIn(true);
fetchUserInfo(kakaoToken); // 토큰이 있으면 사용자 정보 가져오기
fetchUserInfo(kakaoToken);
}
}, []);

Expand All @@ -30,12 +30,17 @@ const MainPage = () => {
}
};

// 새로운 메시지가 추가될 때 페이지를 가장 아래로 스크롤
useEffect(() => {
window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
}, [messages]);

const toggleSidebar = () => {
setSidebarOpen((prev) => !prev);
};

const handleKakaoLogin = () => {
window.location.href = KAKAO_AUTH_URL; // 카카오 로그인 페이지로 이동
window.location.href = KAKAO_AUTH_URL;
};

const fetchUserInfo = async (token: string) => {
Expand Down Expand Up @@ -104,8 +109,8 @@ const SidebarWrapper = styled.div<{ isOpen: boolean }>`
width: ${({ isOpen }) => (isOpen ? "250px" : "0")};
overflow: hidden;
transition: width 0.3s ease-in-out;
background-color: #f0f0f0; // 사이드바 배경 색상 설정
z-index: 1000; // 사이드바가 상단에 표시되도록 설정
background-color: #f0f0f0;
z-index: 1000;
`;

// Wrapper 컴포넌트 스타일
Expand Down
41 changes: 26 additions & 15 deletions src/pages/main/message-input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// message-input.tsx

import { Box, Textarea, IconButton } from "@chakra-ui/react";
import { ArrowUpIcon } from "@chakra-ui/icons";
import styled from "@emotion/styled";
import { useRef, useEffect } from "react";
import { useRef, useEffect, useState } from "react";

interface MessageInputProps {
inputMessage: string;
Expand All @@ -17,28 +15,42 @@ export const MessageInput: React.FC<MessageInputProps> = ({
onSendMessage,
}) => {
const textareaRef = useRef<HTMLTextAreaElement>(null);
const [response, setResponse] = useState(null);
const baseURL = import.meta.env.VITE_BASE_URL; // baseURL 가져오기
console.log("baseURL:", baseURL);

const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setInputMessage(e.target.value); // 입력된 텍스트 상태 업데이트
autoResize(); // 글자 수가 많아질 때 입력창 자동 조정
setInputMessage(e.target.value);
autoResize();
};

const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
onSendMessage(); // 엔터 키로 메시지 전송
onSendMessage();
}
};

const autoResize = () => {
if (textareaRef.current) {
textareaRef.current.style.height = "auto"; // 높이 초기화
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`; // 내용에 맞춰 높이 조정
textareaRef.current.style.height = "auto";
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
}
};

useEffect(() => {
autoResize(); // 초기 렌더링 시 높이 조정
// baseURL을 사용하여 백엔드에서 데이터 가져오기
fetch(`${baseURL}/api/test`)
.then((res) => res.json())
.then((data) => {
setResponse(data);
console.log("Fetched data:", data); // 받은 데이터 콘솔에 출력
})
.catch((error) => console.error("Error fetching data:", error));
}, [baseURL]);

useEffect(() => {
autoResize();
}, [inputMessage]);

return (
Expand All @@ -50,7 +62,7 @@ export const MessageInput: React.FC<MessageInputProps> = ({
onChange={handleInputChange}
onKeyDown={handleKeyDown}
placeholder="Type a message..."
rows={1} // 기본 높이 설정
rows={1}
/>
<FixedIconButton
aria-label="Send message"
Expand All @@ -59,7 +71,7 @@ export const MessageInput: React.FC<MessageInputProps> = ({
variant="ghost"
size="md"
isRound
onClick={onSendMessage} // 전송 버튼 클릭 시 메시지 전송 함수 호출
onClick={onSendMessage}
/>
</TextareaWrapper>
</MessageInputContainer>
Expand Down Expand Up @@ -93,7 +105,7 @@ const StyledTextarea = styled(Textarea)`
outline: none;
width: 100%;
font-size: 16px;
padding-right: 40px; // 아이콘과의 간격을 확보
padding-right: 40px;
resize: none;
overflow: hidden;
max-height: 200px;
Expand All @@ -104,15 +116,14 @@ const StyledTextarea = styled(Textarea)`
}
&:focus {
outline: none;
box-shadow: none; // 포커스 시 파란색 테두리 제거
box-shadow: none;
}
`;

// 아이콘 버튼을 입력창 오른쪽 아래에 고정
const FixedIconButton = styled(IconButton)`
position: absolute;
right: -10px;
bottom: -5px;
background-color: #d7d7d7;
z-index: 10; // 아이콘이 입력창 위에 위치하도록 설정
z-index: 10;
`;
25 changes: 13 additions & 12 deletions src/pages/main/message-list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef } from 'react';
import { Box, Text } from '@chakra-ui/react';
import styled from '@emotion/styled';
import { useEffect, useRef } from "react";
import { Box, Text } from "@chakra-ui/react";
import styled from "@emotion/styled";

interface MessageListProps {
messages: string[];
Expand All @@ -27,15 +27,16 @@ export const MessageList: React.FC<MessageListProps> = ({ messages }) => {
);
};

// 메시지 리스트 컨테이너 스타일 (테두리 제거)
// 메시지 리스트 컨테이너 스타일
const MessageListContainer = styled(Box)`
width: 80%; // 화면의 80% 너비
width: 90%; // 메시지 입력창과 동일한 너비 설정
max-width: 800px; // 입력창의 최대 너비와 맞춤
display: flex;
flex-direction: column-reverse; // 아래에서부터 메시지가 쌓임
max-height: 400px; // 메시지 리스트의 최대 높이 설정
overflow-y: auto; // 스크롤 가능
flex-direction: column-reverse; // 아래에서부터 메시지가 쌓임
min-height: 60vh; // 화면의 60% 높이를 최소 높이로 설정하여 스크롤 공간 확보
overflow: visible; // 메시지 리스트 자체의 스크롤 비활성화
padding: 10px;
margin-bottom: 60px; // 메시지 입력창과 간격을 둠
margin: 0 auto 60px; // 중앙 정렬 및 메시지 입력창과 간격을 둠
`;

// 메시지 박스 스타일 (동적 길이, 우측 정렬)
Expand All @@ -44,7 +45,7 @@ const MessageBox = styled(Box)`
padding: 10px;
background-color: #f0f0f0;
border-radius: 8px;
max-width: 80%; // 메시지 박스의 최대 너비 설정 (화면의 80%)
align-self: flex-end; // 우측 정렬
word-wrap: break-word; // 긴 텍스트가 박스를 넘지 않도록 자동 줄바꿈
max-width: 80%; // 메시지 박스의 최대 너비 설정 (화면의 80%)
align-self: flex-end; // 우측 정렬
word-wrap: break-word; // 긴 텍스트가 박스를 넘지 않도록 자동 줄바꿈
`;
15 changes: 9 additions & 6 deletions src/pages/main/sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// sidebar.tsx

import { Box, IconButton, Flex } from "@chakra-ui/react";
import { ArrowForwardIcon, ArrowBackIcon } from "@chakra-ui/icons"; // 화살표 아이콘 사용
import { ArrowForwardIcon, ArrowBackIcon } from "@chakra-ui/icons";
import styled from "@emotion/styled";
import knuLogo from "@/assets/knuLogo.svg"; // 경북대 로고 이미지 가져오기
import knuLogo from "@/assets/knuLogo.svg";

interface SidebarProps {
isOpen: boolean;
Expand Down Expand Up @@ -56,7 +56,10 @@ export const Sidebar: React.FC<SidebarProps> = ({ isOpen, toggleSidebar }) => {
);
};

const SidebarContainer = styled(Box)<{ isOpen: boolean }>`
// isOpen 속성을 DOM에 전달하지 않도록 처리
const SidebarContainer = styled(Box, {
shouldForwardProp: (prop) => prop !== "isOpen",
})<{ isOpen: boolean }>`
width: 340px;
height: 100vh;
background-color: #fcb9aa;
Expand All @@ -81,7 +84,7 @@ const ToggleButton = styled(IconButton)`
border-radius: 50%;
width: 50px;
height: 50px;
transition: background-color 0.2s, transform 0.2s; // 호버 시 부드러운 효과 추가
transition: background-color 0.2s, transform 0.2s;
display: flex;
align-items: center;
justify-content: center;
Expand All @@ -91,8 +94,8 @@ const ToggleButton = styled(IconButton)`
}
&:hover {
background-color: #e0a89b; // 살짝 어두운 색으로 호버 효과
transform: translateY(-50%) scale(1.1); // 호버 시 버튼 확대
background-color: #e0a89b;
transform: translateY(-50%) scale(1.1);
}
`;

Expand Down
12 changes: 12 additions & 0 deletions src/services/userService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// src/services/userService.ts
import apiClient from "@/api";

export const fetchUserData = async () => {
try {
const response = await apiClient.get("/user");
return response.data;
} catch (error) {
console.error("Error fetching user data:", error);
throw error;
}
};

0 comments on commit 7633328

Please sign in to comment.