11"use client" ;
22
3- import { useMemo } from "react" ;
3+ import { useMutation , useQuery , useQueryClient } from "@tanstack/react-query" ;
4+ import { addToUsersFavorites , deleteFromUsersFavorites } from "@/lib/actions" ;
45import { Heart , Share } from "lucide-react" ;
5- import { Item , PaginatedResponse , Sublet } from "@/lib/types" ;
6+ import { Item , Sublet } from "@/lib/types" ;
67import { ListingActions } from "@/components/listings/detail/ListingActions" ;
78import { ListingImageGallery } from "@/components/listings/detail/ListingImageGallery" ;
89import { ListingInfo } from "@/components/listings/detail/ListingInfo" ;
910import { UserCard } from "@/components/listings/detail/UserCard" ;
1011import { BackButton } from "@/components/listings/detail/BackButton" ;
11- import { addToUsersFavorites , deleteFromUsersFavorites , getUsersFavorites } from "@/lib/actions" ;
12- import { useMutation , useQuery , useQueryClient } from "@tanstack/react-query" ;
1312
1413interface Props {
1514 listing : Item | Sublet ;
16- initialFavorites : PaginatedResponse < Item | Sublet > | null ;
15+ initialIsFavorited : boolean ;
1716}
1817
19- export const ListingDetail = ( { listing, initialFavorites } : Props ) => {
18+ export const ListingDetail = ( { listing, initialIsFavorited } : Props ) => {
2019 const listingType = listing . listing_type ;
2120 const priceLabel = listingType === "sublet" ? "/mo" : undefined ;
2221 const listingOwnerLabel = listingType === "item" ? "Seller" : "Owner" ;
2322 const queryClient = useQueryClient ( ) ;
2423 const favoritesQuery = useQuery ( {
25- queryKey : [ "favorites" ] ,
26- queryFn : getUsersFavorites ,
27- initialData : initialFavorites ?? undefined ,
28- enabled : initialFavorites !== null ,
24+ queryKey : [ "favorite" , listing . id ] ,
25+ queryFn : async ( ) => initialIsFavorited ,
26+ initialData : initialIsFavorited ,
27+ staleTime : Infinity ,
2928 } ) ;
3029
31- const isInsideFavorites = useMemo (
32- ( ) => ! ! favoritesQuery . data ?. results ?. some ( ( favorite ) => favorite . id === listing . id ) ,
33- [ favoritesQuery . data , listing . id ]
34- ) ;
30+ const isInsideFavorites = favoritesQuery . data ?? false ;
3531
3632 const toggleFavoriteMutation = useMutation ( {
3733 mutationFn : async ( shouldFavorite : boolean ) => {
@@ -42,36 +38,16 @@ export const ListingDetail = ({ listing, initialFavorites }: Props) => {
4238 }
4339 } ,
4440 onMutate : async ( shouldFavorite : boolean ) => {
45- await queryClient . cancelQueries ( { queryKey : [ "favorites" ] } ) ;
46- const previous = queryClient . getQueryData < PaginatedResponse < Item | Sublet > > ( [ "favorites" ] ) ;
47-
48- if ( previous ) {
49- const exists = previous . results ?. some ( ( favorite ) => favorite . id === listing . id ) ;
50- let results = previous . results ?? [ ] ;
51-
52- if ( shouldFavorite && ! exists ) {
53- results = [ ...results , listing ] ;
54- }
55- if ( ! shouldFavorite && exists ) {
56- results = results . filter ( ( favorite ) => favorite . id !== listing . id ) ;
57- }
58-
59- queryClient . setQueryData < PaginatedResponse < Item | Sublet > > ( [ "favorites" ] , {
60- ...previous ,
61- results,
62- } ) ;
63- }
64-
41+ await queryClient . cancelQueries ( { queryKey : [ "favorite" , listing . id ] } ) ;
42+ const previous = queryClient . getQueryData < boolean > ( [ "favorite" , listing . id ] ) ;
43+ queryClient . setQueryData ( [ "favorite" , listing . id ] , shouldFavorite ) ;
6544 return { previous } ;
6645 } ,
6746 onError : ( _error , _shouldFavorite , context ) => {
68- if ( context ?. previous ) {
69- queryClient . setQueryData ( [ "favorites" ] , context . previous ) ;
47+ if ( context ?. previous !== undefined ) {
48+ queryClient . setQueryData ( [ "favorite" , listing . id ] , context . previous ) ;
7049 }
7150 } ,
72- onSettled : ( ) => {
73- queryClient . invalidateQueries ( { queryKey : [ "favorites" ] } ) ;
74- } ,
7551 } ) ;
7652
7753 const handleToggleFavorite = async ( ) => {
@@ -86,6 +62,7 @@ export const ListingDetail = ({ listing, initialFavorites }: Props) => {
8662 < Share className = "h-5 w-5" />
8763 < button
8864 type = "button"
65+ className = "cursor-pointer"
8966 onClick = { handleToggleFavorite }
9067 aria-pressed = { isInsideFavorites }
9168 aria-label = { isInsideFavorites ? "Remove from favorites" : "Add to favorites" }
0 commit comments