본문 바로가기
TIL

[supabase] insert, delete 북마크 추가/삭제

by dev__log 2024. 3. 25.

화장실 상세 페이지에서 상단 오른쪽에 즐겨찾기를 누르면 추가/삭제가 되는 기능을 구현하게 되었다. 

 

즐겨찾기 한 화장실인지 체크하기

먼저 이미 즐겨찾기를 한 화장실인지 체크하는 로직이 필요했다.

  • 즐겨찾기를 안 한 경우 - 하얀 별 표시 및 즐겨찾기 추가 기능 수행
  • 즐겨찾기를 한 경우 - 노란 별 표시 및 즐겨찾기 삭제 기능 수행

 

유저가 북마크 한 화장실인지 체크

export const getBookmark = async (user_uid: string, id: number): Promise<Bookmark[]> => {
  try {
    const { data, error } = await supabase
      .from('bookmark')
      .select('*')
      .eq('user_uid', user_uid)
      .eq('toilet_id', id);      

    if (error) {
      console.error('Error fetching data:', error.message);
      return [];
    }

    return data as Bookmark[];
  } catch (error) {
    console.error(error);
    return [];
  }
};

 

북마크 테이블에서 로그인한 유저의 uid와 toilet_id(화장실 id)가 일치하는 데이터가 있다면 이 유저가 이 화장실을 북마크 했다고 판단하기로 했다. 

그래서 데이터를 조회할 때 user_uid, toilet_id를 넘겨주어 조회하였다. 

 

const { user_uid } = useLoggedInUserStore((state) => state.userData);

const { data: bookmarkData } = useQuery<Bookmark[]>({
    queryFn: () => getBookmark(user_uid, id),
    queryKey: ['detailBookmark'],
    enabled: !!user_uid,
  });

 

enabled 옵션으로 user_uid 가 있을 때만 요청을 날리도록 하여 불필요한 요청을 하지 않도록 하였다. 

user_uid는 zustand의 store에서 가져왔다. 

 

북마크 추가하기

import { useRouter } from 'next/navigation';
const router = useRouter();

const handleAddBookMark = async () => {
    if (user_uid === '') {
      alert('로그인 후 사용할 수 있는 서비스입니다. 로그인 페이지로 이동합니다.');
      router.replace('/login_page');
      return;
    }
    const { data, error } = await supabase
      .from('bookmark')
      .insert([{ toilet_id: id, user_uid: user_uid }])
      .select();
    if (error) {
      throw new Error(error?.message || '에러가 발생했습니다!');
    }
    setBookMarkMode((prev) => !prev);
  };

 

user_uid가 없다면 미로그인 상태이기 때문에 로그인 화면으로 이동시킨다. 

북마크 추가 기능이 실행된 후 useState의 값을 반대로 바꾼다.(true로)

 

 

북마크 삭제하기

const handleDeleteBookMark = async () => {
    if (user_uid === '') {
      return;
    }
    await supabase
      .from('bookmark')
      .delete()
      .eq('bookmark_id', bookmarkData?.[0].bookmark_id as number);
    setBookMarkMode((prev) => !prev);
  };

 

bookmarkData?.[0].bookmark_id as number 

bookmarkData가 배열이라서 인덱스 0 인 데이터의 bookmark_id를 넣어서 삭제한다. 

bookmarkData가 1개만 조회될 거라서... 음 이 부분을 개선할 수 있으면 좋을 것 같다...

 

북마크 상태에 따른 렌더링

const [bookMarkMode, setBookMarkMode] = useState(false);

 

북마크 상태에 따라 렌더링을 다르게 해야 하기 때문에 useState에 담아서 관리하고, 

 

useEffect(() => {
    if (bookmarkData && bookmarkData.length > 0) {
      setBookMarkMode(true);
    } else {
      setBookMarkMode(false);
    }
  }, [bookmarkData]);

 

useEffect를 통해 조회한 bookmarkData에 따라서 useState의 상태를 변경했다. 

추가 기능을 실행할지 삭제 기능을 삭제할지는 bookmarkMode useState로 토글 되도록 되어있다. 

 

렌더링 되는 버튼 부분 코드

<button
    className={`flex flex-col text-3xl ${bookMarkMode ? 'text-amber-300' : null} -translate-y-1 items-center gap-1`}
    onClick={bookMarkMode ? handleDeleteBookMark : handleAddBookMark}
  >
    {bookMarkMode ? <FaStar /> : <CiStar />}
    <p className="text-xs text-gray-400">즐겨찾기에 추가하기</p>
  </button>

 

 

결과 화면

'TIL' 카테고리의 다른 글

[tailwind css] 반응형 및 color 셋팅  (0) 2024.03.29
[프로그래머스] 모의고사  (0) 2024.03.28
supabase 테이블 조인하여 조회 / 삭제  (0) 2024.03.21
geolocation, kakao 로컬 rest api 활용  (0) 2024.03.20
Zustand  (2) 2024.03.19