import { useQuery, useMutation, UseQueryOptions, UseMutationOptions } from "@tanstack/react-query"; import { GetRequestPagination, IHttpResponse } from "../types/common"; import { GET_LIST_LOCATIONS_URI, GET_LIST_RECENT_LOCATIONS_RATING_URI, GET_LIST_TOP_LOCATIONS, GET_LOCATION_TAGS_URI, GET_LOCATION_URI, GET_SEARCH_LOCATIONS_URI, POST_CREATE_LOCATION } from "../constants/api"; import { client } from "./config"; interface GetListLocationsArg extends GetRequestPagination { order_by?: number, region_type?: number } interface GetSearchLocations extends GetRequestPagination { name: string filter?: string } // API Functions const fetchListLocations = async ({ page, page_size }: GetListLocationsArg) => { const url = `${GET_LIST_LOCATIONS_URI}?page=${page}&page_size=${page_size}` const response = await client({ method: 'GET', url }) return response.data } const fetchRecentLocationsRatings = async (page_size: number, page: number) => { const url = `${GET_LIST_RECENT_LOCATIONS_RATING_URI}?page_size=${page_size}&page=${page}` const response = await client({ method: 'GET', url }) return response.data } const fetchTopLocations = async ({ page, page_size, order_by, region_type }: GetListLocationsArg) => { const url = `${GET_LIST_TOP_LOCATIONS}?page=${page}&page_size=${page_size}&order_by=${order_by}®ion_type=${region_type}` const response = await client({ method: 'GET', url }) return response.data } interface GetLocationArg { id: number review?: 'user' | 'critics' page?: number page_size?: number } const fetchLocation = async ({ id, review, page, page_size }: GetLocationArg) => { const params = new URLSearchParams() if (review) params.set('review', review) if (page) params.set('page', String(page)) if (page_size) params.set('page_size', String(page_size)) const query = params.toString() const url = `${GET_LOCATION_URI}/${id}${query ? `?${query}` : ''}` const response = await client({ method: 'GET', url }) return response.data } const fetchLocationTags = async (id: number) => { const url = `${GET_LOCATION_TAGS_URI}/${id}` const response = await client({ method: 'GET', url }) return response.data } const createLocation = async (data: FormData) => { const response = await client({ method: 'POST', url: POST_CREATE_LOCATION, data, withCredentials: true }) return response.data } const searchLocations = async (arg: GetSearchLocations) => { const filter = arg.filter ? arg.filter : '' const pageSize = arg.page_size ? arg.page_size : 12 const page = arg.page ? arg.page : 1 const response = await client({ method: 'GET', url: `${GET_SEARCH_LOCATIONS_URI}?name=${arg.name}&filter${filter}&limit=${pageSize}&offset=${page}` }) return response.data } // React Query Hooks export const useListLocations = (params: GetListLocationsArg, options?: Omit, 'queryKey' | 'queryFn'>) => { return useQuery({ queryKey: ['locations', params], queryFn: () => fetchListLocations(params), ...options }) } export const useRecentLocationsRatings = (page_size: number, page: number, options?: Omit, 'queryKey' | 'queryFn'>) => { return useQuery({ queryKey: ['locations', 'recent-ratings', page_size, page], queryFn: () => fetchRecentLocationsRatings(page_size, page), ...options }) } export const useTopLocations = (params: GetListLocationsArg, options?: Omit, 'queryKey' | 'queryFn'>) => { return useQuery({ queryKey: ['locations', 'top', params], queryFn: () => fetchTopLocations(params), ...options }) } export const useLocation = (params: GetLocationArg, options?: Omit, 'queryKey' | 'queryFn'>) => { return useQuery({ queryKey: ['location', params], queryFn: () => fetchLocation(params), enabled: !!params.id, ...options }) } export const useLocationTags = (id: number, options?: Omit, 'queryKey' | 'queryFn'>) => { return useQuery({ queryKey: ['location', 'tags', id], queryFn: () => fetchLocationTags(id), enabled: !!id, ...options }) } export const useSearchLocations = (params: GetSearchLocations, options?: Omit, 'queryKey' | 'queryFn'>) => { return useQuery({ queryKey: ['locations', 'search', params], queryFn: () => searchLocations(params), enabled: !!params.name, ...options }) } export const useCreateLocation = (options?: UseMutationOptions) => { return useMutation({ mutationFn: createLocation, ...options }) } // Legacy service functions for backward compatibility async function getListLocationsService({ page, page_size }: GetListLocationsArg) { try { const data = await fetchListLocations({ page, page_size }) return { data, error: null } } catch (error) { return { data: null, error } } } async function getListRecentLocationsRatingsService(page_size: number, page: number) { try { const data = await fetchRecentLocationsRatings(page_size, page) return { data, error: null } } catch (error) { return { data: null, error } } } async function getListTopLocationsService(params: GetListLocationsArg) { try { const data = await fetchTopLocations(params) return { data, error: null } } catch (error) { return { data: null, error } } } async function getLocationService(params: GetLocationArg) { try { const data = await fetchLocation(params) return { data, error: null } } catch (error) { throw error } } async function getLocationTagsService(id: number) { try { const data = await fetchLocationTags(id) return { data, error: null } } catch (error) { return { data: null, error } } } async function createLocationService(data: FormData): Promise { try { const responseData = await createLocation(data) return { data: responseData, error: null } } catch (error: any) { return { data: null, error, status: error.status } } } async function getSearchLocationService(arg: GetSearchLocations): Promise { try { const data = await searchLocations(arg) return { data, error: null } } catch(error: any) { return { data: null, error, status: error.status } } } export { getListLocationsService, getSearchLocationService, getListRecentLocationsRatingsService, getListTopLocationsService, getLocationTagsService, getLocationService, createLocationService, }