아래 사진의 애플리케이션 추가하기를 누른 후
입력란을 채워준다. (나는 앱 이름과 사업자명을 같게 했다.)
npm start
시 뜨는 주소! (http://localhost:3000)상세페이지에 접속하여 채팅하기 버튼 클릭 시
채팅방 테이블에 현재 로그인 유저와 게시물 작성 유저의 uid가 담긴
row를 하나 insert 한다.
채팅방 테이블에 채팅방이 생성되면
첫 메세지로 내가 클릭한 상품의 { 게시물의 제목, 가격, 관심 있어요! }
라는 세 개의 메세지를 상대방에게 전송한다.
// 채팅하기 버튼 클릭 시
const makeChatRoom = async (e: MouseEvent) => {
// 게시물 작성자의 uid
const targetId = e.currentTarget.id;
// user 테이블에서 채팅 상대 정보 가져오기
// user 테이블의 uid 컬럼 값 === 게시물 작성자의 uid인 것을 가져온다
const { data: targetUser, error: noUser } = await supabase
.from('user')
.select('*')
.eq('uid', targetId);
// 게시물 작성자의 정보가 존재하면
// state에 저장
if (targetUser && targetUser.length > 0) {
setTarget(targetUser[0]);
}
// error 처리 (추후 UI적으로 표현 예정)
if (noUser) console.log('user is not exists', noUser);
};
// 생성된 채팅방 row에 로그인 유저와 채팅 상대 정보 insert 하는 함수
const insertUserIntoChatRoom = async (
curUser: CustomUser,
target: CustomUser
) => {
// participants는 채팅방 테이블의 row가 갖는 채팅 참여자 필드이다.
const participants = [
{
participants: [
{ user_id: target.uid, user_name: target.username },
{
user_id: curUser.uid,
user2_name: curUser.username
}
]
}
];
// 채팅방 테이블의 participants 필드에 참여자 정보 insert
const { data: chatRoom, error } = await supabase
.from('chat_room')
.insert(participants);
// 유저가 속한 채팅방을 반환하는 함수
// 이것은 유저가 속한 채팅방의 id를 얻기 위해 사용합니다
await findRoom();
if (error) console.log('생성 실패');
};
// 유저가 속한 채팅방을 반환해주는 함수
const findRoom = async () => {
const { data: foundRoom, error } = await supabase
.from('chat_room')
.select('*');
if (error) {
console.error('일치하는 방 없음', error);
return;
}
// 채팅 테이블의 row를 읽어와서 (curUser는 현재 로그인 된 유저 정보 state)
if (foundRoom && curUser) {
// 유저가 속한 채팅방을 filter 후
const filtered = foundRoom.filter((room: any) => {
return room.participants.some(
(participant: any) => participant.user_id === curUser.uid
);
});
// 유저가 속한 채팅방 반환
return filtered;
}
};
// 유저 테이블의 chat_rooms 필드값에 방을 업뎃해주자
const insertRoomintoUser = async (userInfo: CustomUser[]) => {
// 헬퍼함수로 유저가 속한 채팅 테이블 할당
const room = (await findRoom()) as any;
// 만약 유저가 속한 채팅방 데이터와 현재 로그인 한 유저 정보가 있다면
if (room && userInfo) {
// 채팅방 id 추출
const room_id = room[0].id;
// 인자로 받은 user 정보의 uid와 같은 필드의 chat_rooms에
// 채팅방 id 추가!
const { data, error } = await supabase
.from('user')
.update({ chat_rooms: [room_id] })
.eq('uid', userInfo[0].uid)
.select();
if (error) {
console.error('채팅방 추가 실패', error.message);
return false;
}
}
};
// 이제 각 유저에게 채팅방을 추가하자
// 현재 로그인 유저, 채팅 상대 유저 정보를 인자로 보내어
// 유저의 chat_room_id에 채팅방 id를 update 해준다 (insertRoomIntoUser 함수)
const findUser = async (User: CustomUser) => {
const { data: userInfo, error } = await supabase
.from('user')
.select('*')
.eq('uid', User?.uid);
if (userInfo) {
await insertRoomIntoUser(userInfo as any);
}
};
// 게시물 관련 데이터를 첫 메세지로 보낸다.
const sendFirstMessage = async () => {
if (product && curUser) {
// 유저가 속한 채팅방을 반환하여 room에 할당
const room = await findRoom();
if (room) {
// 채팅방 생성 시 자동으로 전송되는 메세지
const InitMessage = [
{
sender_id: curUser.uid,
content: `제목: ${product[0].title}`,
chat_room_id: room[0]?.id
},
{
sender_id: curUser.uid,
content: `${product[0].price}원`,
chat_room_id: room[0]?.id
},
{
sender_id: curUser.uid,
content: '이 상품에 관심 있어요!',
chat_room_id: room[0]?.id
}
];
// 메세지 테이블에 시작 메세지 insert
const { data, error } = await supabase
.from('chat_messages')
.insert(InitMessage);
if (error) console.log('메세지 전송 실패..', error);
}
} else console.log('데이터 없음');
};
DB 데이터를 다루는 것에 있어서 뭔가
엄청나게 많은 함수를 선언하고 사용하는데 이게 맞나..? 싶다🥺
좀 더 효율적으로 바꿀 수 있겠다는 생각이 든다.
typescript에서 any를 많이 사용했는데
type은 어떻게 지정해야 되는 것인지 모를 때가 많다..⭐
리팩토링 단계에서는 명시하는 것으로....!!!