Skip to content

Commit

Permalink
Feat: Chat-131-fe-채팅레이아웃-Home 역할분배 라우팅 (#12)
Browse files Browse the repository at this point in the history
* Feat: 로딩중 컴포넌트 UI 완성

* Style: 애니메이션 속도 수정

* Refactor: aiChatBox의 children으로 LeftChatBox를 넣는 구조로 변경

* Feat: 채팅 간단하게 구현해봄

* Fix: 불필요한 변수 제거(setIsLoading)

* Feat: Sprint 2 역할 분배 라우터 설정
  • Loading branch information
Nangniya authored Jan 9, 2024
1 parent 46956f4 commit e9c3ef7
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/components/Headers/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface IProps {
const ChatHeader = ({ children }: IProps) => {
const navigate = useNavigate();
const onGoBack = () => {
navigate(-1);
navigate('/');
};
return (
<div className={styles.container}>
Expand Down
9 changes: 4 additions & 5 deletions src/components/common/AiChatBox.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { ReactNode } from 'react';
import { Dada36, Lulu36, Chichi36 } from '../../assets';
import { useNavigate } from 'react-router-dom';
import LeftChatBox from '../../components/common/LeftChatBox';
import styles from './AiChatBox.module.scss';

interface IProps {
ai: string;
children: ReactNode;
}

const AiChatBox = ({ ai }: IProps) => {
const AiChatBox = ({ ai, children }: IProps) => {
const navigate = useNavigate();
const goToChange = () => {
navigate('/chat/profile');
Expand All @@ -27,9 +28,7 @@ const AiChatBox = ({ ai }: IProps) => {
<p className={styles.aiName} onClick={goToChange}>
{ai === 'dada' ? '다다' : ai === 'lulu' ? '루루' : '치치'}
</p>
<LeftChatBox>이렇게! 이렇게!</LeftChatBox>
<LeftChatBox>{`I'm 진정이에요`}</LeftChatBox>
<LeftChatBox>장충동 왕족발 보쌈!</LeftChatBox>
{children}
</div>
</div>
</>
Expand Down
49 changes: 49 additions & 0 deletions src/components/common/LoadingChat.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
@import '../../styles/variables/colors.scss';

.wrapper {
display: flex;
align-items: center;
gap: 8px;
height: 20px;
}

.dot1 {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: $BK50;
animation: dot1 0.7s infinite;
}

.dot2 {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: $BK70;
animation: dot2 0.7s infinite;
}

.dot3 {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: $BK50;
}

@keyframes dot1 {
from {
background-color: $BK50;
}
to {
background-color: $BK30;
}
}

@keyframes dot2 {
from {
background-color: $BK70;
}
to {
background-color: $BK10;
}
}
13 changes: 13 additions & 0 deletions src/components/common/LoadingChat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import styles from './LoadingChat.module.scss';

const LoadingChat = () => {
return (
<div className={styles.wrapper}>
<div className={styles.dot1}></div>
<div className={styles.dot2}></div>
<div className={styles.dot3}></div>
</div>
);
};

export default LoadingChat;
84 changes: 79 additions & 5 deletions src/pages/Chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,101 @@
import React, { useState, ReactNode } from 'react';
import styles from './Chat.module.scss';
import { Plus } from '../../assets';
import RightChatBox from '../../components/common/RightChatBox';
import ChatHeader from '../../components/Headers/ChatHeader';
import AiChatBox from '../../components/common/AiChatBox';
import LeftChatBox from '../../components/common/LeftChatBox';
import LoadingChat from '../../components/common/LoadingChat';

interface IMessage {
id: number;
type: string;
content: string | ReactNode;
}

const Chat = () => {
const [messages, setMessages] = useState<IMessage[]>([
{ id: Date.now(), type: 'user', content: '공습경보! 공습경보!' },
{ id: Date.now(), type: 'dada', content: "I'm 진정이에요" },
{ id: Date.now(), type: 'user', content: '안녕' },
{ id: Date.now(), type: 'lulu', content: '장충동 왕족발 보쌈!' },
]);
const [inputText, setInputText] = useState('');

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputText(e.target.value);
};

const handleSendMessage = () => {
if (inputText.trim() === '') return;

setMessages((prev) => [
...prev,
{ id: Date.now(), type: 'user', content: inputText },
{ id: Date.now(), type: 'lulu', content: <LoadingChat /> },
]);
setInputText('');
setTimeout(() => {
const aiResponse = 'AI 응답';
setMessages((prevMessages) => {
const updatedMessages = [...prevMessages];
updatedMessages[updatedMessages.length - 1] = {
id: Date.now(),
type: 'lulu',
content: aiResponse,
};
return updatedMessages;
});
}, 1000);
};

return (
<div>
<ChatHeader>다다</ChatHeader>
<div className={styles.messagesContainer}>
<AiChatBox ai="dada" />
<RightChatBox>공습경보! 공습경보!</RightChatBox>
{messages.map((m) =>
m.type === 'dada' ? (
<AiChatBox key={m.id} ai="dada">
<LeftChatBox>{m.content}</LeftChatBox>
</AiChatBox>
) : m.type === 'lulu' ? (
<AiChatBox key={m.id} ai="lulu">
<LeftChatBox>{m.content}</LeftChatBox>
</AiChatBox>
) : m.type === 'chichi' ? (
<AiChatBox key={m.id} ai="chichi">
<LeftChatBox>{m.content}</LeftChatBox>
</AiChatBox>
) : (
<RightChatBox key={m.id}>{m.content}</RightChatBox>
),
)}
{/* <RightChatBox>공습경보! 공습경보!</RightChatBox>
<AiChatBox ai="dada">
<LeftChatBox>이렇게! 이렇게!</LeftChatBox>
</AiChatBox>
<p
className={styles.aiChanged}
>{`대화 상대가 '루루'로 변경되었습니다.`}</p>
<AiChatBox ai="lulu" />
<RightChatBox>안녕</RightChatBox>
<AiChatBox ai="lulu">
<LeftChatBox>
<LoadingChat />
</LeftChatBox>
</AiChatBox> */}
</div>
<div className={styles.inputBox}>
<button className={styles.plusBtn}>
<Plus />
</button>
<input className={styles.input} />
<button className={styles.submitBtn}>전송</button>
<input
className={styles.input}
value={inputText}
onChange={handleInputChange}
/>
<button className={styles.submitBtn} onClick={handleSendMessage}>
전송
</button>
</div>
</div>
);
Expand Down
7 changes: 7 additions & 0 deletions src/pages/Detail/Detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const Detail = () => {
return <div>Detail</div>;
};

export default Detail;
7 changes: 7 additions & 0 deletions src/pages/Home/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const Calendar = () => {
return <div>Calendar</div>;
};

export default Calendar;
15 changes: 14 additions & 1 deletion src/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { useState } from 'react';
import styles from './Home.module.scss';
import Calendar from './Calendar';
import List from './List';

const Home = () => {
return <div className={styles.example}>Home, hello</div>;
const [isList, setIsList] = useState(false);
const toggleMode = () => {
setIsList((prev) => !prev);
};
return (
<div className={styles.example}>
Home, hello
<button onClick={toggleMode}>리스트 화면 전환</button>
{isList ? <List /> : <Calendar />}
</div>
);
};

export default Home;
7 changes: 7 additions & 0 deletions src/pages/Home/List.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const List = () => {
return <div>List</div>;
};

export default List;
10 changes: 10 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Home from './Home/Home';
import Chat from './Chat/Chat';
import Profile from './Chat/Profile';
import DateSelector from '../components/BottomSheets/DateSelector';
import Detail from './Detail/Detail';

const Router = () => {
const router = createBrowserRouter([
Expand Down Expand Up @@ -30,6 +31,15 @@ const Router = () => {
},
],
},
{
path: 'detail',
children: [
{
index: true,
element: <Detail />,
},
],
},
],
},
]);
Expand Down

0 comments on commit e9c3ef7

Please sign in to comment.