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
@@ -133,6 +133,23 @@ function formatPrice(price: number | null, method: string): string {
|
||||
return price.toLocaleString("pt-BR");
|
||||
}
|
||||
|
||||
function formatCustomOffer(amount: number | null | undefined, currency: string | null | undefined): string | null {
|
||||
if (amount === null || amount === undefined || !currency) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (currency) {
|
||||
case "pix":
|
||||
return `R$ ${amount.toFixed(2)}`;
|
||||
case "tibia_coins":
|
||||
return `${Math.round(amount).toLocaleString("pt-BR")} TC`;
|
||||
case "gold_coins":
|
||||
return `${Math.round(amount).toLocaleString("pt-BR")} GP`;
|
||||
default:
|
||||
return amount.toLocaleString("pt-BR");
|
||||
}
|
||||
}
|
||||
|
||||
interface IntentionCardProps {
|
||||
intention: PurchaseIntention;
|
||||
locale?: string;
|
||||
@@ -213,6 +230,10 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
: 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
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -256,6 +277,13 @@ function IntentionCard({ intention, locale = "pt" }: IntentionCardProps) {
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -496,10 +524,7 @@ interface MyPurchaseIntentionsPanelProps {
|
||||
export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntentionsPanelProps) {
|
||||
const { user } = useSession();
|
||||
const [filter, setFilter] = useState<PurchaseIntentionStatus | "all">("all");
|
||||
|
||||
const { intentions, isLoading, refetch } = useMyPurchaseIntentions(
|
||||
filter === "all" ? undefined : filter
|
||||
);
|
||||
const { intentions, isLoading } = useMyPurchaseIntentions();
|
||||
|
||||
// Contar por status
|
||||
const pendingCount = intentions.filter((i) => i.status === "pending").length;
|
||||
@@ -507,6 +532,10 @@ export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntention
|
||||
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 filteredIntentions =
|
||||
filter === "all"
|
||||
? intentions
|
||||
: intentions.filter((intention) => intention.status === filter);
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
@@ -582,7 +611,7 @@ export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntention
|
||||
<Skeleton key={i} className="h-48 w-full" />
|
||||
))}
|
||||
</div>
|
||||
) : intentions.length === 0 ? (
|
||||
) : 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>
|
||||
@@ -597,7 +626,7 @@ export function MyPurchaseIntentionsPanel({ locale = "pt" }: MyPurchaseIntention
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{intentions.map((intention) => (
|
||||
{filteredIntentions.map((intention) => (
|
||||
<IntentionCard key={intention.intention_id} intention={intention} locale={locale} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user