- Introduced "Minhas Intenções" tab visible only to logged-in users. - Integrated MyPurchaseIntentionsPanel and useMyPurchaseIntentions hook. - Added tab badge showing count of pending intentions. - Extended session API to include user’s main character for downstream features.
116 lines
3.7 KiB
TypeScript
116 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { Package, MapPin, DollarSign, Coins, User } from "lucide-react";
|
|
import { Badge } from "@/components/ui/badge";
|
|
import Image from "next/image";
|
|
import type { Chat } from "@/lib/hooks/use-chat";
|
|
|
|
interface ChatHeaderProps {
|
|
chat: Chat;
|
|
currentUserId: number;
|
|
}
|
|
|
|
export function ChatHeader({ chat, currentUserId }: ChatHeaderProps) {
|
|
const listing = chat.listing_cache;
|
|
const otherUser =
|
|
chat.buyer_id === currentUserId ? chat.seller_cache : chat.buyer_cache;
|
|
const [imageError, setImageError] = useState(false);
|
|
|
|
const formatPrice = (price: number | null | undefined, type: "pix" | "tc" | "gp"): string => {
|
|
if (price === null || price === undefined) return "N/A";
|
|
|
|
if (type === "pix") {
|
|
return new Intl.NumberFormat("pt-BR", {
|
|
style: "currency",
|
|
currency: "BRL",
|
|
}).format(price);
|
|
}
|
|
|
|
if (type === "tc") {
|
|
return `${price.toLocaleString("pt-BR")} TC`;
|
|
}
|
|
|
|
if (type === "gp") {
|
|
const gold = price / 1000000;
|
|
if (gold >= 1) {
|
|
return `${gold.toFixed(2)}kk`;
|
|
}
|
|
return `${price.toLocaleString("pt-BR")} gp`;
|
|
}
|
|
|
|
return price.toLocaleString("pt-BR");
|
|
};
|
|
|
|
return (
|
|
<div className="border-b bg-muted/30 p-4 space-y-3">
|
|
{/* Informações do Anúncio */}
|
|
<div className="flex items-start gap-3">
|
|
{/* Imagem do item */}
|
|
<div className="relative w-16 h-16 rounded-lg bg-muted flex items-center justify-center flex-shrink-0 overflow-hidden">
|
|
{listing.item_image_url && !imageError ? (
|
|
<Image
|
|
src={listing.item_image_url}
|
|
alt={listing.item_name}
|
|
fill
|
|
className="object-cover"
|
|
onError={() => setImageError(true)}
|
|
/>
|
|
) : (
|
|
<Package className="h-8 w-8 text-muted-foreground" />
|
|
)}
|
|
</div>
|
|
|
|
{/* Detalhes do anúncio */}
|
|
<div className="flex-1 min-w-0">
|
|
<h3 className="font-semibold text-lg truncate">{listing.item_name}</h3>
|
|
<div className="flex items-center gap-3 text-sm text-muted-foreground mt-1">
|
|
<div className="flex items-center gap-1">
|
|
<MapPin className="h-3 w-3" />
|
|
<span>{listing.server_name}</span>
|
|
</div>
|
|
<div className="flex items-center gap-1">
|
|
<Package className="h-3 w-3" />
|
|
<span>Qtd: 1</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Preços */}
|
|
<div className="flex items-center gap-2 mt-2 flex-wrap">
|
|
{listing.price_pix && (
|
|
<Badge variant="secondary" className="gap-1">
|
|
<DollarSign className="h-3 w-3" />
|
|
{formatPrice(listing.price_pix, "pix")}
|
|
</Badge>
|
|
)}
|
|
{listing.price_tibia_coins && (
|
|
<Badge variant="secondary" className="gap-1">
|
|
<Coins className="h-3 w-3" />
|
|
{formatPrice(listing.price_tibia_coins, "tc")}
|
|
</Badge>
|
|
)}
|
|
{listing.price_gold_coins && (
|
|
<Badge variant="secondary" className="gap-1">
|
|
<Coins className="h-3 w-3" />
|
|
{formatPrice(listing.price_gold_coins, "gp")}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Informações do outro usuário */}
|
|
<div className="flex items-center gap-2 pt-2 border-t">
|
|
<User className="h-4 w-4 text-muted-foreground" />
|
|
<span className="text-sm text-muted-foreground">
|
|
Conversando com:{" "}
|
|
</span>
|
|
<span className="text-sm font-medium">
|
|
{otherUser.character_name || otherUser.username}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|