- Added MongoDB chat/message integration for seller responses - Improved seller response validation and default messaging - Integrated automatic chat creation/update when responding to intentions - Added highest custom offer fields to listing queries and models - Enhanced listing data with top offer information for buyers
120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
export type PurchaseIntentionStatus =
|
|
| "pending"
|
|
| "accepted"
|
|
| "rejected"
|
|
| "expired"
|
|
| "completed";
|
|
|
|
export interface PurchaseIntentionListing {
|
|
listing_id: number;
|
|
item_id: number;
|
|
item_id_unified: number | null;
|
|
item_name: string;
|
|
quantity: number;
|
|
server_name: string;
|
|
seller_id: number;
|
|
price_pix: number | null;
|
|
price_tibia_coins: number | null;
|
|
price_gold_coins: number | null;
|
|
listing_status: string;
|
|
created_at: Date | string;
|
|
description: string | null;
|
|
trade_item_id: number | null;
|
|
trade_item_name: string | null;
|
|
trade_item_quantity: number | null;
|
|
views_count: number;
|
|
favorites_count: number;
|
|
is_featured: boolean;
|
|
image_url: string | null;
|
|
image_local_path: string | null;
|
|
item_category: string | null;
|
|
seller_character_name: string | null;
|
|
seller_username: string | null;
|
|
seller_email: string | null;
|
|
}
|
|
|
|
export interface PurchaseIntention {
|
|
intention_id: number;
|
|
listing_id: number;
|
|
buyer_id: number;
|
|
payment_method: string;
|
|
payment_method_change_count: number;
|
|
custom_offer_amount: number | string | null;
|
|
custom_offer_currency: string | null;
|
|
custom_offer_created_at: Date | string | null;
|
|
chat_id: string | null;
|
|
status: PurchaseIntentionStatus;
|
|
buyer_message: string | null;
|
|
seller_response: string | null;
|
|
created_at: Date | string;
|
|
updated_at: Date | string;
|
|
expires_at: Date | string | null;
|
|
accepted_at: Date | string | null;
|
|
rejected_at: Date | string | null;
|
|
listing: PurchaseIntentionListing | null;
|
|
}
|
|
|
|
interface PurchaseIntentionsResponse {
|
|
success: boolean;
|
|
intentions: PurchaseIntention[];
|
|
count: number;
|
|
}
|
|
|
|
export function useMyPurchaseIntentions() {
|
|
const queryParams = new URLSearchParams();
|
|
queryParams.set("limit", "100");
|
|
|
|
const { data, isLoading, error, refetch } = useQuery<PurchaseIntentionsResponse>({
|
|
queryKey: ["my-purchase-intentions"],
|
|
queryFn: async () => {
|
|
const res = await fetch(`/api/purchase-intentions/my?${queryParams.toString()}`);
|
|
if (!res.ok) {
|
|
if (res.status === 401) {
|
|
throw new Error("Não autenticado");
|
|
}
|
|
throw new Error("Erro ao buscar intenções de compra");
|
|
}
|
|
return res.json();
|
|
},
|
|
staleTime: 1000 * 30, // 30 segundos
|
|
refetchInterval: 1000 * 30, // Refetch a cada 30 segundos
|
|
refetchOnWindowFocus: true,
|
|
refetchOnReconnect: true,
|
|
enabled: true, // Sempre habilitado (autenticação é verificada no backend)
|
|
});
|
|
|
|
const normalizedIntentions = (data?.intentions || []).map((intention) => ({
|
|
...intention,
|
|
custom_offer_amount:
|
|
intention.custom_offer_amount !== null && intention.custom_offer_amount !== undefined
|
|
? Number(intention.custom_offer_amount)
|
|
: null,
|
|
}));
|
|
|
|
return {
|
|
intentions: normalizedIntentions,
|
|
count: data?.count || 0,
|
|
isLoading,
|
|
error,
|
|
refetch,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Hook para invalidar cache de purchase intentions
|
|
*/
|
|
export function useInvalidatePurchaseIntentions() {
|
|
const queryClient = useQueryClient();
|
|
|
|
const invalidate = () => {
|
|
queryClient.invalidateQueries({ queryKey: ["my-purchase-intentions"] });
|
|
};
|
|
|
|
return invalidate;
|
|
}
|
|
|