Skip to content

Commit 2942cee

Browse files
authored
feat: 노션 OAuth 연결 + 노션 페이지 조회 api 연동
2 parents 08facbd + 14419f5 commit 2942cee

File tree

7 files changed

+293
-208
lines changed

7 files changed

+293
-208
lines changed

src/api/assistantAPI.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export const fetchAssistantList = async () => {
2121
},
2222
});
2323

24-
console.log('✅ 응답 데이터:', response.data);
2524
return response.data;
2625
} catch (error) {
2726
console.error(
@@ -74,7 +73,6 @@ export const updateAssistant = async ({ assistantName, actionTags }) => {
7473
'최종 PATCH URL:',
7574
`${API_BASE_URL}/assistantlist/${assistantName}`
7675
);
77-
console.log('보낼 데이터:', { actionTags });
7876

7977
const response = await axios.patch(
8078
`${API_BASE_URL}/assistantlist/${assistantName}`,

src/api/notionAPI.js

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,74 @@
11
import axios from 'axios';
22

3-
// ✅ Notion OAuth 연결 API
3+
const API_BASE_URL = 'https://www.branchify.site/api';
4+
5+
/**
6+
* @param {string} userEmail - 사용자 이메일
7+
* @param {string} assistantName - 어시스턴트 이름
8+
* @returns {Promise<Object>} Notion OAuth 연결 응답 데이터
9+
*/
410
export const connectNotionOAuth = async ({ userEmail, assistantName }) => {
511
try {
612
const response = await axios.get(
713
'https://www.branchify.site/api/oauth/notion/connect',
814
{
9-
params: { userEmail, assistantName }, // ✅ Query Params로 추가
15+
params: { userEmail, assistantName },
1016
headers: {
1117
Authorization: `Bearer ${localStorage.getItem(
1218
'access_token'
1319
)}`,
14-
}, // ✅ 토큰이 필요한 경우 추가
20+
},
21+
maxRedirects: 0,
1522
}
1623
);
24+
1725
return response.data;
1826
} catch (error) {
19-
console.error('❌ Notion OAuth API 요청 실패:', error);
20-
throw error;
27+
if (error.response?.status === 302) {
28+
console.log('Notion OAuth 리디렉트 감지! 새 창에서 열기');
29+
window.location.href = error.response.headers.location;
30+
} else {
31+
console.error('Notion OAuth API 요청 실패:', error);
32+
throw error;
33+
}
2134
}
2235
};
2336

37+
/**
38+
* @param {string} assistantName - 어시스턴트 이름
39+
* @returns {Promise<Object[]>} Notion 페이지 데이터 배열
40+
*/
2441
export const fetchNotionPages = async (assistantName) => {
2542
const token = localStorage.getItem('access_token');
2643

2744
if (!token) {
45+
console.error('인증 토큰이 없습니다.');
2846
throw new Error('인증 토큰이 없습니다.');
2947
}
3048

31-
const response = await axios.get(
32-
'https://www.branchify.site/api/assistantlist/notionPages',
33-
{
34-
headers: {
35-
Authorization: `Bearer ${token}`,
36-
},
37-
params: { assistantName }, // Params 추가
38-
}
39-
);
49+
if (!assistantName) {
50+
console.error('assistantName이 필요합니다.');
51+
throw new Error('assistantName이 필요합니다.');
52+
}
53+
54+
try {
55+
const response = await axios.get(
56+
`${API_BASE_URL}/assistantlist/notionPages`,
57+
{
58+
headers: {
59+
Authorization: `Bearer ${token}`,
60+
},
61+
params: { assistantName },
62+
}
63+
);
4064

41-
return response.data;
65+
console.log('Notion 페이지 데이터:', response.data);
66+
return response.data;
67+
} catch (error) {
68+
console.error(
69+
'Notion 페이지 API 요청 실패:',
70+
error.response?.data || error.message
71+
);
72+
throw error;
73+
}
4274
};

src/components/BotAi/BotStep2.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ const BotStep2 = ({ onNext, onPrev, assistantData }) => {
3939
const mutation = useMutation({
4040
mutationFn: createAssistant,
4141
onSuccess: (data) => {
42-
console.log('Assistant created:', data);
42+
// userEmail을 포함하여 다음 단계로 전달
4343
onNext({
4444
...assistantData,
4545
assistantName: botName,
4646
prompt: botPrompt,
47+
userEmail: data.userEmail, // 서버에서 받은 userEmail 저장
4748
});
4849
},
4950
onError: (error) => {

src/components/BotAi/BotStep3.jsx

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
/** @jsxImportSource @emotion/react */
2-
import { useState } from 'react';
2+
import { useState, useEffect } from 'react';
3+
import { useNavigate } from 'react-router-dom';
34
import { useMutation } from '@tanstack/react-query';
5+
import { fetchNotionPages } from '../../api/notionAPI';
46
import { updateAssistant } from '../../api/assistantAPI';
5-
import { useNavigate } from 'react-router-dom';
67

78
import BotStepPDF from './modal/BotStepPDF';
89
import BotStepNotion from './modal/BotStepNotion';
910
import BotStepDrive from './modal/BotStepDrive';
11+
1012
import notionIcon from '../../assets/icons/notion-icon.png';
1113
import driveIcon from '../../assets/icons/drive.png';
1214
import arrowIcon from '../../assets/icons/right.svg';
@@ -33,17 +35,60 @@ import {
3335
buttonContainerStyle,
3436
} from './BotStep3.styles';
3537

36-
const BotStep3 = ({ onPrev, assistantData }) => {
38+
const BotStep3 = ({ onPrev, assistantData, setAssistantData }) => {
3739
const [selectedKnowledge, setSelectedKnowledge] = useState(null);
3840
const [selectedActions, setSelectedActions] = useState([]);
41+
const [checked, setChecked] = useState(false);
3942
const navigate = useNavigate();
4043

41-
// 지식 추가 (단일 선택)
42-
const toggleKnowledge = (knowledge) => {
43-
setSelectedKnowledge((prev) => (prev === knowledge ? null : knowledge));
44+
console.log('assistantData 확인:', assistantData);
45+
46+
useEffect(() => {
47+
if (assistantData.isConnect === 1) {
48+
fetchNotionPages(assistantData.assistantName)
49+
.then((data) => {
50+
console.log('Notion 페이지 불러오기 성공:', data);
51+
setAssistantData((prev) => ({
52+
...prev,
53+
notionPages: data, // Notion 페이지 저장
54+
}));
55+
setSelectedKnowledge('Notion'); // 모달 자동 열기
56+
})
57+
.catch((error) =>
58+
console.error('Notion 페이지 불러오기 실패:', error)
59+
);
60+
}
61+
}, [assistantData.isConnect]);
62+
63+
// Notion 클릭 핸들러
64+
const handleNotionClick = () => {
65+
if (!assistantData.assistantName || !assistantData.userEmail) {
66+
alert('어시스턴트 정보를 불러올 수 없습니다.');
67+
return;
68+
}
69+
70+
if (checked) {
71+
setSelectedKnowledge('Notion');
72+
} else {
73+
setChecked(true);
74+
const notionAuthURL = `https://www.branchify.site/api/oauth/notion/connect?userEmail=${encodeURIComponent(
75+
assistantData.userEmail
76+
)}&assistantName=${encodeURIComponent(
77+
assistantData.assistantName
78+
)}`;
79+
80+
const notionWindow = window.open(
81+
notionAuthURL,
82+
'_blank',
83+
'width=600,height=700'
84+
);
85+
if (!notionWindow) {
86+
alert('팝업 차단이 활성화되어 있습니다. 팝업을 허용해주세요.');
87+
}
88+
}
4489
};
4590

46-
// 액션 선택 (다중 선택 가능)
91+
// 액션 추가 (다중 선택 가능)
4792
const toggleAction = (action) => {
4893
setSelectedActions((prev) =>
4994
prev.includes(action)
@@ -52,25 +97,22 @@ const BotStep3 = ({ onPrev, assistantData }) => {
5297
);
5398
};
5499

55-
console.log('🔍 assistantData 확인:', assistantData);
56-
console.log('🔍 assistantName 확인:', assistantData?.assistantName);
57-
58100
const isFormValid = selectedActions.length > 0;
59101

60102
const mutation = useMutation({
61103
mutationFn: updateAssistant,
62104
onSuccess: () => {
63-
console.log('Assistant updated successfully');
105+
console.log('Assistant 업데이트 성공!');
64106
alert('봇 생성 완료!');
65107
navigate('/bot/list');
66108
},
67109
onError: (error) => {
68-
console.error('Error updating assistant:', error);
110+
console.error('Assistant 업데이트 실패:', error);
69111
alert('업데이트 실패!');
70112
},
71113
});
72114

73-
const handleCreateBot = async () => {
115+
const handleCreateBot = () => {
74116
if (!assistantData.assistantName) {
75117
alert('Assistant 데이터가 없습니다.');
76118
return;
@@ -106,7 +148,7 @@ const BotStep3 = ({ onPrev, assistantData }) => {
106148
<div css={boxSectionStyle}>
107149
<div
108150
css={boxStyle(selectedKnowledge === 'PDF')}
109-
onClick={() => toggleKnowledge('PDF')}
151+
onClick={() => setSelectedKnowledge('PDF')}
110152
>
111153
<span css={knowledgeText}>PDF</span>
112154
<span css={knowledgeText}>업로드</span>
@@ -115,7 +157,7 @@ const BotStep3 = ({ onPrev, assistantData }) => {
115157
css={boxStyle(
116158
selectedKnowledge === 'Notion'
117159
)}
118-
onClick={() => toggleKnowledge('Notion')}
160+
onClick={handleNotionClick}
119161
>
120162
<img src={notionIcon} alt="Notion" />
121163
<span css={knowledgeText}>Notion</span>
@@ -124,7 +166,9 @@ const BotStep3 = ({ onPrev, assistantData }) => {
124166
css={boxStyle(
125167
selectedKnowledge === 'Drive'
126168
)}
127-
onClick={() => toggleKnowledge('Drive')}
169+
onClick={() =>
170+
setSelectedKnowledge('Drive')
171+
}
128172
>
129173
<img src={driveIcon} alt="Drive" />
130174
<span css={knowledgeText}>Drive</span>
@@ -164,6 +208,7 @@ const BotStep3 = ({ onPrev, assistantData }) => {
164208
</div>
165209
</div>
166210
</div>
211+
167212
<div css={buttonContainerStyle}>
168213
<span css={prevTextStyle} onClick={onPrev}>
169214
이전 페이지로
@@ -189,6 +234,7 @@ const BotStep3 = ({ onPrev, assistantData }) => {
189234
</div>
190235
</div>
191236

237+
{/* 모달 렌더링 */}
192238
{selectedKnowledge && (
193239
<div>
194240
{selectedKnowledge === 'PDF' && (
@@ -198,6 +244,7 @@ const BotStep3 = ({ onPrev, assistantData }) => {
198244
)}
199245
{selectedKnowledge === 'Notion' && (
200246
<BotStepNotion
247+
assistantName={assistantData.assistantName}
201248
onClose={() => setSelectedKnowledge(null)}
202249
/>
203250
)}

0 commit comments

Comments
 (0)