Skip to content

Commit 5304cdf

Browse files
committed
[fix] 로딩 수정, botmessage 로직 수정
1 parent f699df5 commit 5304cdf

File tree

5 files changed

+84
-58
lines changed

5 files changed

+84
-58
lines changed

src/domains/recommend/components/ChatList.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,41 @@ function ChatList({
1919
onScroll={handleCheckBottom}
2020
className="absolute top-0 left-0 bottom-18 sm:bottom-21 w-full gap-5 px-3 pt-12 pb-4 flex flex-col items-center overflow-y-auto pr-2"
2121
>
22-
<div className="max-w-1024 w-full">
23-
{messages.map((msg) => {
22+
<div className="max-w-1024 w-full flex flex-col gap-5">
23+
{messages.map((msg, i) => {
24+
const keyId = msg.id ?? `temp-${msg.sender}-${i}-${Date.now()}`;
25+
const prevMsg = messages[i - 1];
26+
const showProfile = !prevMsg || prevMsg.sender !== msg.sender;
27+
2428
if (msg.sender === 'USER') {
25-
return <UserMessage key={`${msg.id}-${msg.sender}`} message={msg.message} />;
29+
return (
30+
<UserMessage
31+
key={`${msg.id}-${msg.sender}`}
32+
message={msg.message}
33+
showProfile={showProfile}
34+
/>
35+
);
2636
}
2737

38+
const isTyping = msg.type === 'TYPING';
39+
2840
return (
2941
<BotMessage
30-
key={`${msg.id}-${msg.sender}`}
42+
key={`${keyId}-${msg.sender}`}
3143
messages={[
3244
{
3345
id: msg.id,
34-
message: msg.type === 'TYPING' ? '' : msg.message,
46+
message: msg.message,
3547
type: msg.type ?? 'TEXT',
3648
options: msg.type === 'RADIO_OPTIONS' ? (msg.stepData?.options ?? []) : [],
3749
recommendations: getRecommendations(msg.type, msg.stepData),
3850
},
3951
]}
52+
showProfile={showProfile}
4053
stepData={msg.stepData}
4154
currentStep={userCurrentStep}
4255
onSelectedOption={onSelectedOption}
56+
isTyping={isTyping}
4357
/>
4458
);
4559
})}

src/domains/recommend/components/ChatSection.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,21 @@ import ChatList from './ChatList';
1919

2020
function ChatSection() {
2121
const [messages, setMessages] = useState<ChatMessage[]>([]);
22-
2322
const [userCurrentStep, setUserCurrentStep] = useState(0);
24-
const [isBotTyping, setIsBotTyping] = useState(false);
25-
2623
const selectedOptions = useRef<{
2724
selectedAlcoholStrength?: string;
2825
selectedAlcoholBaseType?: string;
2926
selectedCocktailType?: string;
3027
}>({});
3128

3229
const handleSendMessage = async (payload: stepPayload | { message: string; userId: string }) => {
33-
// Typing 임시메시지
30+
const tempTypingId = `typing-${Date.now()}`;
31+
32+
// Typing 메시지 임시 추가
3433
setMessages((prev) => [
3534
...prev,
3635
{
37-
id: 'typing',
36+
id: tempTypingId,
3837
sender: 'CHATBOT',
3938
type: 'TYPING',
4039
message: '',
@@ -50,11 +49,10 @@ function ChatSection() {
5049

5150
if (!botMessage) return;
5251

53-
// Typing 임시메시지 제거 후 실제 메시지 추가
54-
setMessages((prev) => [...prev.filter((m) => m.type !== 'TYPING'), botMessage]);
52+
setMessages((prev) => prev.map((msg) => (msg.id === tempTypingId ? botMessage : msg)));
5553
} catch (err) {
5654
console.error(err);
57-
setMessages((prev) => prev.filter((m) => m.type !== 'TYPING'));
55+
setMessages((prev) => prev.filter((msg) => msg.id !== tempTypingId));
5856
}
5957
};
6058

@@ -166,7 +164,6 @@ function ChatSection() {
166164
userCurrentStep={userCurrentStep}
167165
onSelectedOption={handleSelectedOption}
168166
getRecommendations={getRecommendations}
169-
isBotTyping={isBotTyping}
170167
/>
171168
<MessageInput onSubmit={handleSubmitText} />
172169
</section>

src/domains/recommend/components/bot/BotMessage.tsx

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,70 @@ interface BotMessage {
1818

1919
interface BotMessages {
2020
messages: BotMessage[];
21+
showProfile: boolean;
2122
stepData?: StepRecommendation | null;
2223
currentStep?: number;
23-
children?: React.ReactNode;
2424
onSelectedOption?: (value: string) => void;
25+
isTyping?: boolean;
2526
}
2627

27-
function BotMessage({ messages, stepData, currentStep, onSelectedOption, children }: BotMessages) {
28+
function BotMessage({
29+
messages,
30+
showProfile,
31+
stepData,
32+
currentStep,
33+
onSelectedOption,
34+
isTyping,
35+
}: BotMessages) {
2836
const [selected, setSelected] = useState('');
2937

3038
return (
3139
<article aria-label="취향추천 챗봇 메시지" className="">
32-
<header className="flex items-end">
33-
<div className="relative w-15 md:w-20 h-15 md:h-20">
34-
<Image
35-
src={Ssury}
36-
alt="쑤리아바타"
37-
width={80}
38-
height={80}
39-
className="object-cover w-15 h-15 md:w-20 md:h-20"
40-
/>
41-
</div>
42-
<strong>쑤리</strong>
43-
</header>
40+
{showProfile && (
41+
<header className="flex items-end">
42+
<div className="relative w-15 md:w-20 h-15 md:h-20">
43+
<Image
44+
src={Ssury}
45+
alt="쑤리아바타"
46+
width={80}
47+
height={80}
48+
className="object-cover w-15 h-15 md:w-20 md:h-20"
49+
/>
50+
</div>
51+
<strong>쑤리</strong>
52+
</header>
53+
)}
4454

4555
{/* 메시지 그룹 */}
4656
<div className="flex flex-col gap-3 mt-3 pl-3">
4757
{messages.map((msg) => (
4858
<div key={msg.id}>
59+
<div className="flex flex-col w-fit max-w-[80%] min-w-[120px] p-3 rounded-2xl rounded-tl-none bg-white text-black opacity-0 animate-fadeIn">
60+
<div>
61+
{isTyping ? (
62+
<TypingIndicator />
63+
) : (
64+
<p className="whitespace-pre-line">{msg.message}</p>
65+
)}
66+
</div>
67+
68+
{/* radio */}
69+
{msg.type === 'RADIO_OPTIONS' && msg.options?.length && (
70+
<BotOptions
71+
options={msg.options}
72+
step={stepData?.currentStep ?? 0}
73+
currentStep={currentStep ?? 0}
74+
value={selected}
75+
onChange={(val) => {
76+
setSelected(val);
77+
onSelectedOption?.(val);
78+
}}
79+
/>
80+
)}
81+
{/* {children} */}
82+
</div>
4983
{msg.type === 'CARD_LIST' && msg.recommendations?.length ? (
50-
<ul className="inline-grid grid-cols-1 sm:grid-cols-3 gap-2 justify-start">
84+
<ul className="inline-grid grid-cols-1 mt-5 sm:grid-cols-3 gap-2 justify-start">
5185
{msg.recommendations.map((rec) => (
5286
<li key={rec.cocktailId}>
5387
<BotCocktailCard
@@ -61,29 +95,7 @@ function BotMessage({ messages, stepData, currentStep, onSelectedOption, childre
6195
))}
6296
</ul>
6397
) : (
64-
<div className="flex flex-col w-fit max-w-[80%] min-w-[120px] p-3 rounded-2xl rounded-tl-none bg-white text-black opacity-0 animate-fadeIn">
65-
{msg.type === 'TYPING' ? (
66-
<TypingIndicator />
67-
) : (
68-
// 실제 메시지 내용
69-
<p className="whitespace-pre-line">{msg.message}</p>
70-
)}
71-
72-
{/* radio */}
73-
{msg.type === 'RADIO_OPTIONS' && msg.options?.length && (
74-
<BotOptions
75-
options={msg.options}
76-
step={stepData?.currentStep ?? 0}
77-
currentStep={currentStep ?? 0}
78-
value={selected}
79-
onChange={(val) => {
80-
setSelected(val);
81-
onSelectedOption?.(val);
82-
}}
83-
/>
84-
)}
85-
{/* {children} */}
86-
</div>
98+
''
8799
)}
88100
</div>
89101
))}

src/domains/recommend/components/user/UserMessage.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
interface Props {
22
message: string;
3+
showProfile: boolean;
34
}
45

56
// 메시지 (연속 메시지) 예시..
@@ -12,12 +13,14 @@ interface Props {
1213
// { id: '2', sender: 'user', text: '배고파요' },
1314
// ];
1415

15-
function UserMessage({ message }: Props) {
16+
function UserMessage({ message, showProfile }: Props) {
1617
return (
1718
<article aria-label="내 메시지" className="flex flex-col items-end">
18-
<header className="w-fit">
19-
<strong></strong>
20-
</header>
19+
{showProfile && (
20+
<header className="w-fit">
21+
<strong></strong>
22+
</header>
23+
)}
2124

2225
{/* 메시지 그룹 */}
2326
<div className="flex flex-col items-end gap-3 mt-3 pr-3 max-w-[80%]">

src/domains/recommend/types/recommend.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface ChatMessage {
2828
type?: string;
2929
stepData?: StepRecommendation | null;
3030
createdAt: string;
31+
tempTyping?: boolean;
3132
}
3233

3334
export interface ChatHistoryItem {
@@ -59,6 +60,5 @@ export interface ChatListProps {
5960
type: string | undefined,
6061
stepData?: StepRecommendation | null
6162
) => RecommendationItem[];
62-
63-
isBotTyping: boolean;
63+
isBotTyping?: boolean;
6464
}

0 commit comments

Comments
 (0)