feat: enhance purchase intentions with chat integration and offer tracking
- 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
This commit is contained in:
1 parent
d27526e026
commit
d8e7d5d7e6
19 files changed
+806
-58
No files matched your search
@@ -68,10 +68,12 @@ interface Listing {
|
||||
// Campo do vendedor
|
||||
seller_character_name?: string | null;
|
||||
has_pending_intention_for_current_user?: boolean;
|
||||
highest_custom_offer_amount?: number | string | null;
|
||||
highest_custom_offer_currency?: string | null;
|
||||
}
|
||||
|
||||
interface PriceInfo {
|
||||
type: "pix" | "tc" | "gp" | "trade";
|
||||
type: "pix" | "tibia_coins" | "gold_coins" | "trade";
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
@@ -227,7 +229,7 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
: listing.price_tibia_coins;
|
||||
if (!isNaN(price)) {
|
||||
prices.push({
|
||||
type: "tc",
|
||||
type: "tibia_coins",
|
||||
label: "TC",
|
||||
value: `${price.toLocaleString()} TC`,
|
||||
});
|
||||
@@ -241,7 +243,7 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
: listing.price_gold_coins;
|
||||
if (!isNaN(price)) {
|
||||
prices.push({
|
||||
type: "gp",
|
||||
type: "gold_coins",
|
||||
label: "GP",
|
||||
value: `${price.toLocaleString()} GP`,
|
||||
});
|
||||
@@ -266,6 +268,35 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
const isSold = listing.listing_status === "sold";
|
||||
const hasPendingIntention = Boolean(listing.has_pending_intention_for_current_user);
|
||||
|
||||
const getHighestOfferLabel = () => {
|
||||
if (
|
||||
listing.highest_custom_offer_amount === null ||
|
||||
listing.highest_custom_offer_amount === undefined ||
|
||||
!listing.highest_custom_offer_currency
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const amount =
|
||||
typeof listing.highest_custom_offer_amount === "string"
|
||||
? Number(listing.highest_custom_offer_amount)
|
||||
: listing.highest_custom_offer_amount;
|
||||
if (Number.isNaN(amount)) {
|
||||
return null;
|
||||
}
|
||||
switch (listing.highest_custom_offer_currency) {
|
||||
case "pix":
|
||||
return `Maior oferta: R$ ${amount.toFixed(2)}`;
|
||||
case "tibia_coins":
|
||||
return `Maior oferta: ${Math.round(amount).toLocaleString()} TC`;
|
||||
case "gold_coins":
|
||||
return `Maior oferta: ${Math.round(amount).toLocaleString()} GP`;
|
||||
default:
|
||||
return `Maior oferta: ${amount}`;
|
||||
}
|
||||
};
|
||||
|
||||
const highestOfferLabel = getHighestOfferLabel();
|
||||
|
||||
// Função para obter URL da imagem do item
|
||||
const getItemImageUrl = (): string => {
|
||||
// Prioridade 1: image_url (URL externa) se disponível
|
||||
@@ -327,9 +358,9 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
switch (type) {
|
||||
case "pix":
|
||||
return "bg-green-100 hover:bg-green-200 dark:bg-green-900/30 dark:hover:bg-green-900/50 text-green-700 dark:text-green-300 border-green-300 dark:border-green-700";
|
||||
case "tc":
|
||||
case "tibia_coins":
|
||||
return "bg-blue-100 hover:bg-blue-200 dark:bg-blue-900/30 dark:hover:bg-blue-900/50 text-blue-700 dark:text-blue-300 border-blue-300 dark:border-blue-700";
|
||||
case "gp":
|
||||
case "gold_coins":
|
||||
return "bg-amber-100 hover:bg-amber-200 dark:bg-amber-900/30 dark:hover:bg-amber-900/50 text-amber-700 dark:text-amber-300 border-amber-300 dark:border-amber-700";
|
||||
case "trade":
|
||||
return "bg-purple-100 hover:bg-purple-200 dark:bg-purple-900/30 dark:hover:bg-purple-900/50 text-purple-700 dark:text-purple-300 border-purple-300 dark:border-purple-700";
|
||||
@@ -342,8 +373,8 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
switch (type) {
|
||||
case "pix":
|
||||
return <DollarSign className="h-3 w-3" />;
|
||||
case "tc":
|
||||
case "gp":
|
||||
case "tibia_coins":
|
||||
case "gold_coins":
|
||||
return <Coins className="h-3 w-3" />;
|
||||
case "trade":
|
||||
return <RefreshCw className="h-3 w-3" />;
|
||||
@@ -554,7 +585,14 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
listing.is_featured && "p-2 rounded-lg border-l-4 bg-yellow-500/5 border-yellow-500",
|
||||
"overflow-hidden"
|
||||
)}>
|
||||
<PriceBadges prices={availablePrices} compact tradeItemImageUrl={tradeItemImageUrl} listing={listing} />
|
||||
<div className="space-y-1">
|
||||
<PriceBadges prices={availablePrices} compact tradeItemImageUrl={tradeItemImageUrl} listing={listing} />
|
||||
{highestOfferLabel && (
|
||||
<div className="text-xs font-medium text-primary/80">
|
||||
{highestOfferLabel}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -846,7 +884,14 @@ export function AdCard({ listing, viewMode = "grid" }: AdCardProps) {
|
||||
listing.is_featured && "p-2 rounded-lg border-l-4 bg-yellow-500/5 border-yellow-500",
|
||||
"overflow-hidden"
|
||||
)}>
|
||||
<PriceBadges prices={availablePrices} tradeItemImageUrl={tradeItemImageUrl} listing={listing} />
|
||||
<div className="space-y-1">
|
||||
<PriceBadges prices={availablePrices} tradeItemImageUrl={tradeItemImageUrl} listing={listing} />
|
||||
{highestOfferLabel && (
|
||||
<div className="text-xs font-medium text-primary/80">
|
||||
{highestOfferLabel}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in new issue
Block a user