style: clean up code formatting and remove trailing whitespace
refactor: reorganize imports and fix type imports
This commit is contained in:
1 parent
d3704602fd
commit
47c04de6fe
232 files changed
+7140
-4798
No files matched your search
@@ -1,31 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import {
|
||||
Clock,
|
||||
CheckCircle2,
|
||||
XCircle,
|
||||
MessageSquare,
|
||||
ShoppingCart,
|
||||
MapPin,
|
||||
Package,
|
||||
User,
|
||||
ExternalLink,
|
||||
AlertCircle,
|
||||
DollarSign,
|
||||
CheckCircle2,
|
||||
Clock,
|
||||
Coins,
|
||||
DollarSign,
|
||||
ExternalLink,
|
||||
MapPin,
|
||||
MessageSquare,
|
||||
Package,
|
||||
RefreshCw,
|
||||
ShoppingCart,
|
||||
User,
|
||||
XCircle,
|
||||
} from "lucide-react";
|
||||
import { useMyPurchaseIntentions, type PurchaseIntention, type PurchaseIntentionStatus } from "@/lib/hooks/use-purchase-intentions";
|
||||
import { useSession } from "@/lib/hooks/use-session";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { ChatModal } from "@/components/chat/ChatModal";
|
||||
import { ChangePaymentMethodButton } from "@/components/purchase-intentions/ChangePaymentMethodButton";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -33,14 +30,22 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { ChatModal } from "@/components/chat/ChatModal";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
type PurchaseIntention,
|
||||
type PurchaseIntentionStatus,
|
||||
useMyPurchaseIntentions,
|
||||
} from "@/lib/hooks/use-purchase-intentions";
|
||||
import { useSession } from "@/lib/hooks/use-session";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function formatTimeAgo(date: Date | string): string {
|
||||
const dateObj = typeof date === "string" ? new Date(date) : date;
|
||||
const seconds = Math.floor((new Date().getTime() - dateObj.getTime()) / 1000);
|
||||
const seconds = Math.floor((Date.now() - dateObj.getTime()) / 1000);
|
||||
if (seconds < 60) return "há alguns segundos";
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
if (minutes < 60) return `há ${minutes} ${minutes === 1 ? "minuto" : "minutos"}`;
|
||||
if (minutes < 60)
|
||||
return `há ${minutes} ${minutes === 1 ? "minuto" : "minutos"}`;
|
||||
const hours = Math.floor(minutes / 60);
|
||||
if (hours < 24) return `há ${hours} ${hours === 1 ? "hora" : "horas"}`;
|
||||
const days = Math.floor(hours / 24);
|
||||
@@ -55,35 +60,50 @@ function getStatusBadge(status: PurchaseIntentionStatus) {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return (
|
||||
<Badge variant="secondary" className="bg-yellow-500/20 text-yellow-700 dark:text-yellow-400">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-yellow-500/20 text-yellow-700 dark:text-yellow-400"
|
||||
>
|
||||
<Clock className="h-3 w-3 mr-1" />
|
||||
Pendente
|
||||
</Badge>
|
||||
);
|
||||
case "accepted":
|
||||
return (
|
||||
<Badge variant="secondary" className="bg-green-500/20 text-green-700 dark:text-green-400">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-green-500/20 text-green-700 dark:text-green-400"
|
||||
>
|
||||
<CheckCircle2 className="h-3 w-3 mr-1" />
|
||||
Aceita
|
||||
</Badge>
|
||||
);
|
||||
case "rejected":
|
||||
return (
|
||||
<Badge variant="secondary" className="bg-red-500/20 text-red-700 dark:text-red-400">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-red-500/20 text-red-700 dark:text-red-400"
|
||||
>
|
||||
<XCircle className="h-3 w-3 mr-1" />
|
||||
Rejeitada
|
||||
</Badge>
|
||||
);
|
||||
case "expired":
|
||||
return (
|
||||
<Badge variant="secondary" className="bg-gray-500/20 text-gray-700 dark:text-gray-400">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-gray-500/20 text-gray-700 dark:text-gray-400"
|
||||
>
|
||||
<AlertCircle className="h-3 w-3 mr-1" />
|
||||
Expirada
|
||||
</Badge>
|
||||
);
|
||||
case "completed":
|
||||
return (
|
||||
<Badge variant="secondary" className="bg-blue-500/20 text-blue-700 dark:text-blue-400">
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="bg-blue-500/20 text-blue-700 dark:text-blue-400"
|
||||
>
|
||||
<CheckCircle2 className="h-3 w-3 mr-1" />
|
||||
Concluída
|
||||
</Badge>
|
||||
@@ -110,18 +130,18 @@ function getPaymentMethodLabel(method: string): string {
|
||||
|
||||
function formatPrice(price: number | null, method: string): string {
|
||||
if (price === null) return "N/A";
|
||||
|
||||
|
||||
if (method === "pix") {
|
||||
return new Intl.NumberFormat("pt-BR", {
|
||||
style: "currency",
|
||||
currency: "BRL",
|
||||
}).format(price);
|
||||
}
|
||||
|
||||
|
||||
if (method === "tibia_coins") {
|
||||
return `${price.toLocaleString("pt-BR")} TC`;
|
||||
}
|
||||
|
||||
|
||||
if (method === "gold_coins") {
|
||||
const gold = price / 1000000;
|
||||
if (gold >= 1) {
|
||||
@@ -129,11 +149,14 @@ function formatPrice(price: number | null, method: string): string {
|
||||
}
|
||||
return `${price.toLocaleString("pt-BR")} gp`;
|
||||
}
|
||||
|
||||
|
||||
return price.toLocaleString("pt-BR");
|
||||
}
|
||||
|
||||
function formatCustomOffer(amount: number | null | undefined, currency: string | null | undefined): string | null {
|
||||
function formatCustomOffer(
|
||||
amount: number | null | undefined,
|
||||
currency: string | null | undefined,
|
||||
): string | null {
|
||||
if (amount === null || amount === undefined || !currency) {
|
||||
return null;
|
||||
}
|
||||
@@ -171,7 +194,9 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<h3 className="font-semibold text-lg">Anúncio não disponível</h3>
|
||||
<h3 className="font-semibold text-lg">
|
||||
Anúncio não disponível
|
||||
</h3>
|
||||
{getStatusBadge(intention.status)}
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
@@ -203,7 +228,9 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
return `/api/images?path=${encodeURIComponent(`data/images/${category}/${normalizedPath}`)}`;
|
||||
}
|
||||
if (listing.item_id_unified) {
|
||||
const params = new URLSearchParams({ item: listing.item_id_unified.toString() });
|
||||
const params = new URLSearchParams({
|
||||
item: listing.item_id_unified.toString(),
|
||||
});
|
||||
if (listing.item_name) {
|
||||
params.set("name", listing.item_name);
|
||||
}
|
||||
@@ -223,24 +250,27 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
? `${listing.listing_id}_${intention.buyer_id}_${listing.seller_id}`
|
||||
: null);
|
||||
|
||||
const price = listing.price_pix && intention.payment_method === "pix"
|
||||
? listing.price_pix
|
||||
: listing.price_tibia_coins && intention.payment_method === "tibia_coins"
|
||||
? listing.price_tibia_coins
|
||||
: listing.price_gold_coins && intention.payment_method === "gold_coins"
|
||||
? listing.price_gold_coins
|
||||
: null;
|
||||
const price =
|
||||
listing.price_pix && intention.payment_method === "pix"
|
||||
? listing.price_pix
|
||||
: listing.price_tibia_coins && intention.payment_method === "tibia_coins"
|
||||
? listing.price_tibia_coins
|
||||
: listing.price_gold_coins && intention.payment_method === "gold_coins"
|
||||
? listing.price_gold_coins
|
||||
: null;
|
||||
const customOfferLabel = formatCustomOffer(
|
||||
typeof intention.custom_offer_amount === "number" ? intention.custom_offer_amount : null,
|
||||
intention.custom_offer_currency ?? null
|
||||
typeof intention.custom_offer_amount === "number"
|
||||
? intention.custom_offer_amount
|
||||
: null,
|
||||
intention.custom_offer_currency ?? null,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card className="hover:shadow-md transition-shadow">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex items-start gap-4 flex-1 min-w-0">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="flex items-start gap-4 flex-1 min-w-0">
|
||||
<div className="relative w-16 h-16 rounded-lg bg-muted flex items-center justify-center flex-shrink-0 overflow-hidden">
|
||||
{itemImageUrl ? (
|
||||
<Image
|
||||
@@ -254,160 +284,172 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<h3 className="font-semibold text-lg truncate">{listing.item_name}</h3>
|
||||
{getStatusBadge(intention.status)}
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground mb-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<MapPin className="h-3 w-3" />
|
||||
<span>{listing.server_name}</span>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<h3 className="font-semibold text-lg truncate">
|
||||
{listing.item_name}
|
||||
</h3>
|
||||
{getStatusBadge(intention.status)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Package className="h-3 w-3" />
|
||||
<span>Qtd: {listing.quantity}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<ShoppingCart className="h-3 w-3" />
|
||||
<span>{getPaymentMethodLabel(intention.payment_method)}</span>
|
||||
{price !== null && (
|
||||
<span className="font-medium text-foreground ml-1">
|
||||
{formatPrice(price, intention.payment_method)}
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground mb-2">
|
||||
<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: {listing.quantity}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<ShoppingCart className="h-3 w-3" />
|
||||
<span>
|
||||
{getPaymentMethodLabel(intention.payment_method)}
|
||||
</span>
|
||||
{price !== null && (
|
||||
<span className="font-medium text-foreground ml-1">
|
||||
{formatPrice(price, intention.payment_method)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{customOfferLabel && (
|
||||
<div className="flex items-center gap-1 text-foreground">
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="border-primary text-primary"
|
||||
>
|
||||
Sua oferta: {customOfferLabel}
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{customOfferLabel && (
|
||||
<div className="flex items-center gap-1 text-foreground">
|
||||
<Badge variant="outline" className="border-primary text-primary">
|
||||
Sua oferta: {customOfferLabel}
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-3">
|
||||
{/* Informações do vendedor */}
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<User className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-muted-foreground">Vendedor:</span>
|
||||
<span className="font-medium">
|
||||
{listing.seller_character_name || listing.seller_username || "Desconhecido"}
|
||||
</span>
|
||||
</div>
|
||||
<CardContent className="space-y-3">
|
||||
{/* Informações do vendedor */}
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<User className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-muted-foreground">Vendedor:</span>
|
||||
<span className="font-medium">
|
||||
{listing.seller_character_name ||
|
||||
listing.seller_username ||
|
||||
"Desconhecido"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Mensagem do comprador */}
|
||||
{intention.buyer_message && (
|
||||
<div className="bg-muted/50 rounded-md p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<MessageSquare className="h-4 w-4 text-muted-foreground mt-0.5 flex-shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-xs text-muted-foreground mb-1">Sua mensagem:</p>
|
||||
<p className="text-sm">{intention.buyer_message}</p>
|
||||
{/* Mensagem do comprador */}
|
||||
{intention.buyer_message && (
|
||||
<div className="bg-muted/50 rounded-md p-3">
|
||||
<div className="flex items-start gap-2">
|
||||
<MessageSquare className="h-4 w-4 text-muted-foreground mt-0.5 flex-shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-xs text-muted-foreground mb-1">
|
||||
Sua mensagem:
|
||||
</p>
|
||||
<p className="text-sm">{intention.buyer_message}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
|
||||
{/* Resposta do vendedor */}
|
||||
{intention.seller_response && (
|
||||
<div
|
||||
className={cn(
|
||||
"rounded-md p-3 border",
|
||||
intention.status === "accepted"
|
||||
? "bg-green-500/10 border-green-500/20"
|
||||
: intention.status === "rejected"
|
||||
? "bg-red-500/10 border-red-500/20"
|
||||
: "bg-blue-500/10 border-blue-500/20"
|
||||
{/* Resposta do vendedor */}
|
||||
{intention.seller_response && (
|
||||
<div
|
||||
className={cn(
|
||||
"rounded-md p-3 border",
|
||||
intention.status === "accepted"
|
||||
? "bg-green-500/10 border-green-500/20"
|
||||
: intention.status === "rejected"
|
||||
? "bg-red-500/10 border-red-500/20"
|
||||
: "bg-blue-500/10 border-blue-500/20",
|
||||
)}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<MessageSquare
|
||||
className={cn(
|
||||
"h-4 w-4 mt-0.5 flex-shrink-0",
|
||||
intention.status === "accepted"
|
||||
? "text-green-600 dark:text-green-400"
|
||||
: intention.status === "rejected"
|
||||
? "text-red-600 dark:text-red-400"
|
||||
: "text-blue-600 dark:text-blue-400",
|
||||
)}
|
||||
/>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-xs font-medium mb-1">
|
||||
{intention.status === "accepted"
|
||||
? "Resposta do vendedor (Aceita):"
|
||||
: intention.status === "rejected"
|
||||
? "Resposta do vendedor (Rejeitada):"
|
||||
: "Resposta do vendedor:"}
|
||||
</p>
|
||||
<p className="text-sm">{intention.seller_response}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Timestamps */}
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground pt-2 border-t">
|
||||
<div className="flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" />
|
||||
<span>Criada {formatTimeAgo(intention.created_at)}</span>
|
||||
</div>
|
||||
{intention.updated_at !== intention.created_at && (
|
||||
<span>Atualizada {formatTimeAgo(intention.updated_at)}</span>
|
||||
)}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<MessageSquare
|
||||
className={cn(
|
||||
"h-4 w-4 mt-0.5 flex-shrink-0",
|
||||
intention.status === "accepted"
|
||||
? "text-green-600 dark:text-green-400"
|
||||
: intention.status === "rejected"
|
||||
? "text-red-600 dark:text-red-400"
|
||||
: "text-blue-600 dark:text-blue-400"
|
||||
)}
|
||||
/>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-xs font-medium mb-1">
|
||||
{intention.status === "accepted"
|
||||
? "Resposta do vendedor (Aceita):"
|
||||
: intention.status === "rejected"
|
||||
? "Resposta do vendedor (Rejeitada):"
|
||||
: "Resposta do vendedor:"}
|
||||
</p>
|
||||
<p className="text-sm">{intention.seller_response}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Timestamps */}
|
||||
<div className="flex items-center justify-between text-xs text-muted-foreground pt-2 border-t">
|
||||
<div className="flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" />
|
||||
<span>Criada {formatTimeAgo(intention.created_at)}</span>
|
||||
</div>
|
||||
{intention.updated_at !== intention.created_at && (
|
||||
<span>Atualizada {formatTimeAgo(intention.updated_at)}</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center gap-2 pt-2 flex-wrap">
|
||||
{intention.status === "pending" &&
|
||||
intention.payment_method_change_count < 1 && (
|
||||
<ChangePaymentMethodButton
|
||||
intentionId={intention.intention_id}
|
||||
currentPaymentMethod={intention.payment_method}
|
||||
availableMethods={[
|
||||
...(listing.price_pix ? ["pix"] : []),
|
||||
...(listing.price_tibia_coins ? ["tibia_coins"] : []),
|
||||
...(listing.price_gold_coins ? ["gold_coins"] : []),
|
||||
...(listing.trade_item_id ? ["trade"] : []),
|
||||
]}
|
||||
canChange={true}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setShowListingModal(true)}
|
||||
className="flex-1"
|
||||
>
|
||||
<ExternalLink className="h-4 w-4 mr-2" />
|
||||
Ver Anúncio
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="flex-1"
|
||||
onClick={() => setShowChatModal(true)}
|
||||
>
|
||||
<MessageSquare className="h-4 w-4 mr-2" />
|
||||
Abrir Chat
|
||||
</Button>
|
||||
{intention.status === "accepted" && listing.listing_status === "active" && (
|
||||
{/* Actions */}
|
||||
<div className="flex items-center gap-2 pt-2 flex-wrap">
|
||||
{intention.status === "pending" &&
|
||||
intention.payment_method_change_count < 1 && (
|
||||
<ChangePaymentMethodButton
|
||||
intentionId={intention.intention_id}
|
||||
currentPaymentMethod={intention.payment_method}
|
||||
availableMethods={[
|
||||
...(listing.price_pix ? ["pix"] : []),
|
||||
...(listing.price_tibia_coins ? ["tibia_coins"] : []),
|
||||
...(listing.price_gold_coins ? ["gold_coins"] : []),
|
||||
...(listing.trade_item_id ? ["trade"] : []),
|
||||
]}
|
||||
canChange={true}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setShowListingModal(true)}
|
||||
className="flex-1"
|
||||
>
|
||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
||||
Comprar Agora
|
||||
<ExternalLink className="h-4 w-4 mr-2" />
|
||||
Ver Anúncio
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="flex-1"
|
||||
onClick={() => setShowChatModal(true)}
|
||||
>
|
||||
<MessageSquare className="h-4 w-4 mr-2" />
|
||||
Abrir Chat
|
||||
</Button>
|
||||
{intention.status === "accepted" &&
|
||||
listing.listing_status === "active" && (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => setShowListingModal(true)}
|
||||
className="flex-1"
|
||||
>
|
||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
||||
Comprar Agora
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Dialog open={showListingModal} onOpenChange={setShowListingModal}>
|
||||
<DialogContent className="max-w-2xl">
|
||||
<DialogHeader>
|
||||
@@ -434,30 +476,48 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">{listing.item_name}</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1">{listing.description ?? "Sem descrição fornecida para este anúncio."}</p>
|
||||
<p className="text-sm text-muted-foreground mt-1">
|
||||
{listing.description ??
|
||||
"Sem descrição fornecida para este anúncio."}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<MapPin className="h-4 w-4" />
|
||||
<span>Servidor: <span className="font-medium text-foreground">{listing.server_name}</span></span>
|
||||
<span>
|
||||
Servidor:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{listing.server_name}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<Package className="h-4 w-4" />
|
||||
<span>Quantidade: <span className="font-medium text-foreground">{listing.quantity}</span></span>
|
||||
<span>
|
||||
Quantidade:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{listing.quantity}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-muted-foreground">
|
||||
<User className="h-4 w-4" />
|
||||
<span>Vendedor:{" "}
|
||||
<span>
|
||||
Vendedor:{" "}
|
||||
<span className="font-medium text-foreground">
|
||||
{listing.seller_character_name || listing.seller_username || "Desconhecido"}
|
||||
{listing.seller_character_name ||
|
||||
listing.seller_username ||
|
||||
"Desconhecido"}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<h4 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">Condições de pagamento</h4>
|
||||
<h4 className="text-sm font-medium text-muted-foreground uppercase tracking-wide">
|
||||
Condições de pagamento
|
||||
</h4>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{listing.price_pix && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
@@ -477,18 +537,23 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
{formatPrice(listing.price_gold_coins, "gold_coins")}
|
||||
</Badge>
|
||||
)}
|
||||
{listing.trade_item_id && listing.trade_item_name && listing.trade_item_quantity && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
{listing.trade_item_quantity}x {listing.trade_item_name}
|
||||
</Badge>
|
||||
)}
|
||||
{listing.trade_item_id &&
|
||||
listing.trade_item_name &&
|
||||
listing.trade_item_quantity && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
{listing.trade_item_quantity}x {listing.trade_item_name}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button variant="outline" asChild>
|
||||
<Link href={`/${locale}/market?listing=${listing.listing_id}`} target="_blank">
|
||||
<Link
|
||||
href={`/${locale}/market?listing=${listing.listing_id}`}
|
||||
target="_blank"
|
||||
>
|
||||
Abrir no marketplace
|
||||
</Link>
|
||||
</Button>
|
||||
@@ -521,17 +586,25 @@ interface MyPurchaseIntentionsPanelProps {
|
||||
locale?: string;
|
||||
}
|
||||
|
||||
export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntentionsPanelProps) {
|
||||
export function MyPurchaseIntentionsPanel({
|
||||
locale = "pt",
|
||||
}: MyPurchaseIntentionsPanelProps) {
|
||||
const { user } = useSession();
|
||||
const [filter, setFilter] = useState<PurchaseIntentionStatus | "all">("all");
|
||||
const { intentions, isLoading } = useMyPurchaseIntentions();
|
||||
|
||||
// Contar por status
|
||||
const pendingCount = intentions.filter((i) => i.status === "pending").length;
|
||||
const acceptedCount = intentions.filter((i) => i.status === "accepted").length;
|
||||
const rejectedCount = intentions.filter((i) => i.status === "rejected").length;
|
||||
const acceptedCount = intentions.filter(
|
||||
(i) => i.status === "accepted",
|
||||
).length;
|
||||
const rejectedCount = intentions.filter(
|
||||
(i) => i.status === "rejected",
|
||||
).length;
|
||||
const expiredCount = intentions.filter((i) => i.status === "expired").length;
|
||||
const completedCount = intentions.filter((i) => i.status === "completed").length;
|
||||
const completedCount = intentions.filter(
|
||||
(i) => i.status === "completed",
|
||||
).length;
|
||||
const filteredIntentions =
|
||||
filter === "all"
|
||||
? intentions
|
||||
@@ -540,7 +613,9 @@ export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntention
|
||||
if (!user) {
|
||||
return (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-muted-foreground">Faça login para ver suas intenções de compra</p>
|
||||
<p className="text-muted-foreground">
|
||||
Faça login para ver suas intenções de compra
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -614,7 +689,9 @@ export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntention
|
||||
) : filteredIntentions.length === 0 ? (
|
||||
<div className="text-center py-12 border rounded-lg">
|
||||
<ShoppingCart className="h-12 w-12 mx-auto mb-4 text-muted-foreground opacity-50" />
|
||||
<p className="text-lg font-medium mb-2">Nenhuma intenção de compra encontrada</p>
|
||||
<p className="text-lg font-medium mb-2">
|
||||
Nenhuma intenção de compra encontrada
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
{filter === "all"
|
||||
? "Quando você manifestar interesse em comprar um item, ele aparecerá aqui."
|
||||
@@ -627,11 +704,14 @@ export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntention
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{filteredIntentions.map((intention) => (
|
||||
<IntentionCard key={intention.intention_id} intention={intention} locale={locale} />
|
||||
<IntentionCard
|
||||
key={intention.intention_id}
|
||||
intention={intention}
|
||||
locale={locale}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user