화장실 상세 페이지에서 상단 오른쪽에 즐겨찾기를 누르면 추가/삭제가 되는 기능을 구현하게 되었다.
즐겨찾기 한 화장실인지 체크하기
먼저 이미 즐겨찾기를 한 화장실인지 체크하는 로직이 필요했다.
- 즐겨찾기를 안 한 경우 - 하얀 별 표시 및 즐겨찾기 추가 기능 수행
- 즐겨찾기를 한 경우 - 노란 별 표시 및 즐겨찾기 삭제 기능 수행
유저가 북마크 한 화장실인지 체크
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 |