almeira-web/dripzone-app/src/app/admin/feed-whatsapp/page.tsx

715 lines
30 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import {
Radio,
Sparkles,
RefreshCw,
Search,
CheckCircle2,
XCircle,
Plus,
Send,
Layers,
ShoppingBag,
ExternalLink,
MessageSquare,
ShieldCheck,
Zap,
Filter,
CheckSquare,
Square,
Edit3,
Trash2,
ArrowUpRight,
Eye,
} from 'lucide-react';
import { SupplierPost, Product, MonitoredWhatsAppGroup } from '@/types';
import { formatCOP } from '@/lib/pricing-engine';
import { BRANDS, BrandId } from '@/config/brands';
export default function SupplierFeedPage() {
const [posts, setPosts] = useState<SupplierPost[]>([]);
const [monitoredGroups, setMonitoredGroups] = useState<MonitoredWhatsAppGroup[]>([]);
const [selectedGroupFilter, setSelectedGroupFilter] = useState<string>('all');
const [tabStatus, setTabStatus] = useState<'pending' | 'published' | 'discarded'>('pending');
const [isLoading, setIsLoading] = useState(false);
const [isSyncingLive, setIsSyncingLive] = useState(false);
const [actionMessage, setActionMessage] = useState<string | null>(null);
// Multi-selection state
const [selectedPostIds, setSelectedPostIds] = useState<Set<string>>(new Set());
// Edit Modal State
const [editingPost, setEditingPost] = useState<SupplierPost | null>(null);
const [editName, setEditName] = useState('');
const [editBrand, setEditBrand] = useState('');
const [editPrice, setEditPrice] = useState(120000);
const [editSizes, setEditSizes] = useState('');
// Target brand selector for publishing
const [targetBrand, setTargetBrand] = useState<BrandId | 'all'>('almeira');
// Cargar grupos monitoreados y posts iniciales en vivo
const loadInitialData = async () => {
setIsLoading(true);
try {
// 1. Grupos
const grpRes = await fetch('/api/whatsapp-groups?fetchLive=true');
const grpData = await grpRes.json();
if (grpData.success && Array.isArray(grpData.groups)) {
setMonitoredGroups(grpData.groups);
}
// 2. Posts en vivo desde los grupos de WhatsApp
const feedRes = await fetch('/api/whatsapp-feed?fetchLive=true&limit=50');
const feedData = await feedRes.json();
if (feedData.success && Array.isArray(feedData.posts)) {
setPosts(feedData.posts);
}
} catch (err) {
console.error('Error cargando feed:', err);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
loadInitialData();
}, []);
// Cambiar filtro de grupo y recargar mensajes
const handleGroupFilterChange = async (groupJid: string) => {
setSelectedGroupFilter(groupJid);
setIsSyncingLive(true);
setActionMessage(null);
try {
const url =
groupJid !== 'all'
? `/api/whatsapp-feed?fetchLive=true&groupJid=${encodeURIComponent(groupJid)}`
: '/api/whatsapp-feed?fetchLive=true&limit=50';
const res = await fetch(url);
const data = await res.json();
if (data.success && Array.isArray(data.posts)) {
setPosts(data.posts);
setActionMessage(
`✅ Se cargaron ${data.totalFound || data.posts.length} mensajes del grupo.`
);
}
} catch (err) {
console.error(err);
setActionMessage('❌ Error cargando mensajes del grupo.');
} finally {
setIsSyncingLive(false);
}
};
// Sincronizar mensajes en vivo desde Evolution API
const handleSyncLive = async () => {
setIsSyncingLive(true);
setActionMessage(null);
try {
const url =
selectedGroupFilter !== 'all'
? `/api/whatsapp-feed?fetchLive=true&groupJid=${encodeURIComponent(selectedGroupFilter)}`
: '/api/whatsapp-feed?fetchLive=true&limit=50';
const res = await fetch(url);
const data = await res.json();
if (data.success && Array.isArray(data.posts)) {
setPosts(data.posts);
setActionMessage(
`✅ ¡Sincronización completa! Se escanearon ${data.totalFound || data.posts.length} mensajes recientes de WhatsApp.`
);
} else {
setActionMessage('⚠️ No se encontraron mensajes nuevos en los grupos seleccionados.');
}
} catch (err: any) {
console.error(err);
setActionMessage('❌ Error conectando con Evolution API para traer mensajes.');
} finally {
setIsSyncingLive(false);
}
};
// Publicar un producto a la tienda
const handlePublishPost = async (
post: SupplierPost,
customData?: { name?: string; brand?: string; retailPrice?: number; sizes?: string[] }
) => {
try {
const res = await fetch('/api/whatsapp-feed', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'publish',
post,
customName: customData?.name,
customRetailPrice: customData?.retailPrice,
customSizes: customData?.sizes,
}),
});
const data = await res.json();
if (data.success) {
setPosts((prev) =>
prev.map((p) => (p.id === post.id ? { ...p, status: 'published' } : p))
);
setActionMessage(`🚀 ¡"${data.product.name}" ha sido publicado en la App Móvil y Web!`);
if (editingPost?.id === post.id) setEditingPost(null);
}
} catch (e) {
console.error(e);
setActionMessage('❌ Error al publicar producto.');
}
};
// Publicación masiva de los seleccionados
const handleBulkPublish = async () => {
const selectedPosts = posts.filter(
(p) => selectedPostIds.has(p.id) && p.status !== 'published'
);
if (selectedPosts.length === 0) return;
setIsLoading(true);
try {
const res = await fetch('/api/whatsapp-feed', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'bulk-publish',
posts: selectedPosts,
}),
});
const data = await res.json();
if (data.success) {
setPosts((prev) =>
prev.map((p) => (selectedPostIds.has(p.id) ? { ...p, status: 'published' } : p))
);
setSelectedPostIds(new Set());
setActionMessage(
`🎉 ¡Éxito! Se han publicado ${data.products?.length || selectedPosts.length} zapatillas en la App Móvil y Web.`
);
}
} catch (e) {
console.error(e);
setActionMessage('❌ Error en publicación masiva.');
} finally {
setIsLoading(false);
}
};
// Descartar mensaje
const handleDiscardPost = async (post: SupplierPost) => {
try {
await fetch('/api/whatsapp-feed', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'discard', post }),
});
setPosts((prev) =>
prev.map((p) => (p.id === post.id ? { ...p, status: 'discarded' } : p))
);
setSelectedPostIds((prev) => {
const next = new Set(prev);
next.delete(post.id);
return next;
});
} catch (e) {
console.error(e);
}
};
// Manejo de Selección
const handleToggleSelect = (id: string) => {
setSelectedPostIds((prev) => {
const next = new Set(prev);
if (next.has(id)) next.delete(id);
else next.add(id);
return next;
});
};
// Filtrado de posts por estado y grupo
const filteredPosts = posts.filter((p) => {
// Estado
if (tabStatus === 'pending' && p.status === 'published') return false;
if (tabStatus === 'pending' && p.status === 'discarded') return false;
if (tabStatus === 'published' && p.status !== 'published') return false;
if (tabStatus === 'discarded' && p.status !== 'discarded') return false;
// Grupo
if (selectedGroupFilter !== 'all') {
return (p as any).channelJid === selectedGroupFilter || p.channelName === selectedGroupFilter;
}
return true;
});
const pendingCount = posts.filter((p) => p.status !== 'published' && p.status !== 'discarded').length;
const publishedCount = posts.filter((p) => p.status === 'published').length;
const discardedCount = posts.filter((p) => p.status === 'discarded').length;
const handleOpenEdit = (post: SupplierPost) => {
setEditingPost(post);
setEditName(post.extractedProduct?.name || 'Zapatilla Urbana');
setEditBrand(post.extractedProduct?.brand || 'Nike');
setEditPrice(
post.extractedProduct?.suggestedRetailPrice ||
(post.extractedProduct?.supplierPrice ? post.extractedProduct.supplierPrice + 35000 : 125000)
);
setEditSizes(post.extractedProduct?.sizes?.join(', ') || '38, 39, 40, 41, 42, 43');
};
return (
<div className="space-y-6">
{/* Header */}
<div className="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
<div>
<div className="flex items-center gap-2">
<div className="w-9 h-9 rounded-xl bg-purple-500/20 text-purple-400 flex items-center justify-center border border-purple-500/30 shadow-[0_0_15px_rgba(168,85,247,0.3)]">
<Radio className="w-5 h-5 animate-pulse" />
</div>
<div>
<h1 className="text-2xl font-black text-white">Feed de Mensajes de WhatsApp</h1>
<p className="text-xs text-neutral-400">
Visualiza los mensajes de tus grupos de proveedores y selecciona los calzados que deseas publicar en la app móvil.
</p>
</div>
</div>
</div>
{/* Action Controls */}
<div className="flex items-center gap-2.5 flex-wrap">
<Link
href="/admin/grupos-whatsapp"
className="bg-neutral-900 hover:bg-neutral-800 border border-neutral-700 text-neutral-300 font-bold text-xs px-3.5 py-2.5 rounded-xl flex items-center gap-1.5 transition-all"
>
<MessageSquare className="w-4 h-4 text-purple-400" />
<span>Gestionar Grupos</span>
</Link>
<button
onClick={handleSyncLive}
disabled={isSyncingLive}
className="bg-gradient-to-r from-purple-600 to-fuchsia-600 hover:opacity-95 text-white font-black text-xs px-4 py-2.5 rounded-xl flex items-center gap-2 shadow-lg shadow-purple-600/30 cursor-pointer transition-all active:scale-95 disabled:opacity-50"
>
<RefreshCw className={`w-4 h-4 ${isSyncingLive ? 'animate-spin' : ''}`} />
<span>{isSyncingLive ? 'Consultando Grupos...' : 'Sincronizar WhatsApp en Vivo'}</span>
</button>
</div>
</div>
{/* Toast feedback */}
{actionMessage && (
<div className="bg-purple-950/80 border border-purple-500/50 text-purple-200 px-4 py-3 rounded-2xl text-xs flex items-center justify-between animate-in fade-in shadow-xl">
<div className="flex items-center gap-2">
<Sparkles className="w-4 h-4 text-purple-400" />
<span>{actionMessage}</span>
</div>
<button
onClick={() => setActionMessage(null)}
className="text-white hover:text-purple-300 font-bold px-2 cursor-pointer"
>
✕
</button>
</div>
)}
{/* Filter & Tabs Bar */}
<div className="bg-neutral-900/90 border border-neutral-800 rounded-3xl p-4 flex flex-col md:flex-row items-stretch md:items-center justify-between gap-4 backdrop-blur-xl">
{/* Status Tabs */}
<div className="flex items-center gap-1 bg-neutral-950 p-1 rounded-2xl border border-neutral-800 text-xs font-bold">
<button
onClick={() => setTabStatus('pending')}
className={`px-3.5 py-2 rounded-xl transition-all cursor-pointer flex items-center gap-1.5 ${
tabStatus === 'pending'
? 'bg-purple-600 text-white shadow'
: 'text-neutral-400 hover:text-white'
}`}
>
<span>📥 Pendientes</span>
<span className="bg-purple-950 text-purple-300 text-[10px] px-1.5 py-0.5 rounded-full font-mono">
{pendingCount}
</span>
</button>
<button
onClick={() => setTabStatus('published')}
className={`px-3.5 py-2 rounded-xl transition-all cursor-pointer flex items-center gap-1.5 ${
tabStatus === 'published'
? 'bg-emerald-600 text-white shadow'
: 'text-neutral-400 hover:text-white'
}`}
>
<span>✅ Publicados en Tienda</span>
<span className="bg-emerald-950 text-emerald-300 text-[10px] px-1.5 py-0.5 rounded-full font-mono">
{publishedCount}
</span>
</button>
<button
onClick={() => setTabStatus('discarded')}
className={`px-3.5 py-2 rounded-xl transition-all cursor-pointer flex items-center gap-1.5 ${
tabStatus === 'discarded'
? 'bg-neutral-800 text-white shadow'
: 'text-neutral-400 hover:text-white'
}`}
>
<span>🗑️ Descartados</span>
<span className="bg-neutral-900 text-neutral-400 text-[10px] px-1.5 py-0.5 rounded-full font-mono">
{discardedCount}
</span>
</button>
</div>
{/* Group Selector Filter */}
<div className="flex items-center gap-2">
<Filter className="w-4 h-4 text-purple-400 shrink-0" />
<select
value={selectedGroupFilter}
onChange={(e) => handleGroupFilterChange(e.target.value)}
className="bg-neutral-950 border border-neutral-800 text-white text-xs font-semibold rounded-xl px-3 py-2 outline-hidden cursor-pointer"
>
<option value="all">Todos los Grupos de WhatsApp</option>
{monitoredGroups.map((g) => (
<option key={g.id || g.jid} value={g.jid}>
{g.name}
</option>
))}
</select>
</div>
</div>
{/* Multi-Selection Bulk Actions Bar */}
{selectedPostIds.size > 0 && tabStatus === 'pending' && (
<div className="bg-gradient-to-r from-purple-950/90 to-neutral-900 border border-purple-500/40 rounded-2xl p-3.5 flex items-center justify-between animate-in fade-in shadow-2xl">
<div className="flex items-center gap-2.5">
<span className="bg-purple-600 text-white text-xs font-black px-2.5 py-1 rounded-lg">
{selectedPostIds.size} seleccionados
</span>
<span className="text-xs text-neutral-300 font-semibold hidden sm:inline">
Listos para transferir al catálogo de la tienda
</span>
</div>
<div className="flex items-center gap-2">
<button
onClick={() => setSelectedPostIds(new Set())}
className="text-neutral-400 hover:text-white text-xs font-bold px-3 py-1.5 rounded-xl cursor-pointer"
>
Desmarcar
</button>
<button
onClick={handleBulkPublish}
className="bg-gradient-to-r from-purple-600 to-fuchsia-500 hover:opacity-95 text-white text-xs font-black px-4 py-2 rounded-xl flex items-center gap-1.5 shadow-lg shadow-purple-600/30 cursor-pointer transition-all active:scale-95"
>
<Plus className="w-4 h-4" />
<span>Publicar Seleccionados ({selectedPostIds.size})</span>
</button>
</div>
</div>
)}
{/* Posts List / Grid */}
{filteredPosts.length === 0 ? (
<div className="bg-neutral-900/60 rounded-3xl p-12 text-center border border-neutral-800 space-y-4">
<div className="w-16 h-16 rounded-2xl bg-purple-500/10 border border-purple-500/20 text-purple-400 flex items-center justify-center mx-auto">
<MessageSquare className="w-8 h-8" />
</div>
<div className="space-y-1">
<h3 className="font-black text-white text-base">No hay mensajes en esta bandeja</h3>
<p className="text-xs text-neutral-400 max-w-md mx-auto">
Haz clic en <strong>"Sincronizar WhatsApp en Vivo"</strong> para extraer automáticamente las ofertas recientes de tus grupos seleccionados.
</p>
</div>
<button
onClick={handleSyncLive}
disabled={isSyncingLive}
className="bg-purple-600 hover:bg-purple-500 text-white font-bold text-xs px-5 py-2.5 rounded-xl inline-flex items-center gap-2 cursor-pointer shadow-md"
>
<RefreshCw className={`w-4 h-4 ${isSyncingLive ? 'animate-spin' : ''}`} />
<span>Escanear Grupos Ahora</span>
</button>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{filteredPosts.map((post) => {
const extracted = post.extractedProduct;
const isSelected = selectedPostIds.has(post.id);
const isPublished = post.status === 'published';
const isDiscarded = post.status === 'discarded';
return (
<div
key={post.id}
className={`bg-neutral-900 border rounded-3xl p-5 space-y-4 transition-all ${
isSelected
? 'border-purple-500 shadow-[0_0_20px_rgba(168,85,247,0.2)]'
: isPublished
? 'border-emerald-500/30 bg-emerald-950/10'
: 'border-neutral-800 hover:border-neutral-700'
}`}
>
{/* Header info */}
<div className="flex items-center justify-between gap-2 border-b border-neutral-800 pb-3">
<div className="flex items-center gap-2">
{tabStatus === 'pending' && (
<button
onClick={() => handleToggleSelect(post.id)}
className="text-purple-400 hover:text-purple-300 cursor-pointer"
>
{isSelected ? (
<CheckSquare className="w-5 h-5 fill-purple-600 text-white" />
) : (
<Square className="w-5 h-5 text-neutral-600" />
)}
</button>
)}
<div>
<span className="bg-purple-950 text-purple-300 text-[10px] font-black px-2 py-0.5 rounded-full border border-purple-500/30 inline-block">
{post.channelName || 'Grupo WhatsApp'}
</span>
<span className="text-[10px] text-neutral-500 ml-2 font-mono">{post.receivedAt}</span>
</div>
</div>
<div>
{isPublished ? (
<span className="bg-emerald-500/20 text-emerald-300 border border-emerald-500/40 text-[10px] font-bold px-2.5 py-0.5 rounded-full flex items-center gap-1">
<CheckCircle2 className="w-3 h-3" /> Publicado en Tienda
</span>
) : isDiscarded ? (
<span className="bg-neutral-800 text-neutral-400 text-[10px] font-bold px-2.5 py-0.5 rounded-full">
Descartado
</span>
) : (
<span className="bg-amber-500/20 text-amber-300 border border-amber-500/40 text-[10px] font-bold px-2.5 py-0.5 rounded-full flex items-center gap-1">
<Sparkles className="w-3 h-3" /> Pendiente de Aprobación
</span>
)}
</div>
</div>
{/* Content Grid (Photo + AI extracted info) */}
<div className="grid grid-cols-1 sm:grid-cols-12 gap-4">
{/* Sneaker Image & Raw text */}
<div className="sm:col-span-5 space-y-2">
<div className="relative aspect-square w-full rounded-2xl overflow-hidden bg-neutral-950 border border-neutral-800 flex items-center justify-center group">
{post.rawImages && post.rawImages[0] ? (
<img
src={post.rawImages[0]}
alt={extracted?.name || 'Zapatilla'}
className="w-full h-full object-cover group-hover:scale-105 transition-all"
/>
) : (
<div className="text-neutral-600 text-xs">Sin foto</div>
)}
</div>
{/* Raw WhatsApp Message snippet */}
<div className="bg-neutral-950 rounded-xl p-2.5 border border-neutral-800/80">
<p className="text-[11px] text-neutral-400 font-mono whitespace-pre-line line-clamp-3">
{post.rawMessage}
</p>
</div>
</div>
{/* AI Extraction & Product Info */}
<div className="sm:col-span-7 space-y-3 flex flex-col justify-between">
<div className="space-y-2">
<div>
<span className="text-[10px] font-black uppercase text-purple-400 tracking-wider">
{extracted?.brand || 'Nike'} • {extracted?.category || 'Sneakers'}
</span>
<h3 className="text-base font-black text-white leading-tight">
{extracted?.name || 'Zapatilla Urbana'}
</h3>
</div>
{/* Pricing breakdown */}
<div className="bg-neutral-950 p-3 rounded-2xl border border-neutral-800 grid grid-cols-2 gap-2">
<div>
<span className="text-[10px] text-neutral-400 block font-bold">Costo Proveedor:</span>
<span className="text-xs font-bold text-neutral-300 font-mono">
{formatCOP(extracted?.supplierPrice || 90000)}
</span>
</div>
<div>
<span className="text-[10px] text-emerald-400 block font-bold">Venta Sugerida:</span>
<span className="text-sm font-black text-emerald-300 font-mono">
{formatCOP(extracted?.suggestedRetailPrice || 125000)}
</span>
</div>
</div>
{/* Sizes badge pills */}
<div>
<span className="text-[10px] font-bold text-neutral-400 uppercase block mb-1">
Tallas Disponibles:
</span>
<div className="flex gap-1 flex-wrap">
{extracted?.sizes && extracted.sizes.length > 0 ? (
extracted.sizes.map((s) => (
<span
key={s}
className="bg-neutral-950 text-white font-bold text-[11px] px-2 py-0.5 rounded-lg border border-neutral-800"
>
{s}
</span>
))
) : (
<span className="text-xs text-neutral-500">37 a 43</span>
)}
</div>
</div>
</div>
{/* Card Actions */}
<div className="pt-2 border-t border-neutral-800 flex items-center gap-2">
{!isPublished ? (
<>
<button
onClick={() => handlePublishPost(post)}
className="flex-1 bg-gradient-to-r from-purple-600 to-fuchsia-600 hover:opacity-95 text-white font-black text-xs py-2.5 px-3 rounded-xl flex items-center justify-center gap-1.5 shadow-md shadow-purple-600/30 cursor-pointer transition-all active:scale-95"
>
<Plus className="w-3.5 h-3.5" />
<span>Publicar en la App</span>
</button>
<button
onClick={() => handleOpenEdit(post)}
title="Editar antes de publicar"
className="bg-neutral-800 hover:bg-neutral-700 text-neutral-300 p-2.5 rounded-xl cursor-pointer transition-all"
>
<Edit3 className="w-4 h-4" />
</button>
<button
onClick={() => handleDiscardPost(post)}
title="Descartar"
className="bg-neutral-800 hover:bg-red-950/40 text-neutral-400 hover:text-red-400 p-2.5 rounded-xl cursor-pointer transition-all"
>
<Trash2 className="w-4 h-4" />
</button>
</>
) : (
<div className="w-full flex items-center justify-between text-xs">
<span className="text-emerald-400 font-bold flex items-center gap-1">
<CheckCircle2 className="w-4 h-4" /> Disponible para clientes
</span>
<Link
href="/"
target="_blank"
className="text-purple-400 hover:underline font-bold flex items-center gap-1"
>
<span>Ver en Tienda</span>
<ArrowUpRight className="w-3 h-3" />
</Link>
</div>
)}
</div>
</div>
</div>
</div>
);
})}
</div>
)}
{/* Edit Modal Before Publishing */}
{editingPost && (
<div className="fixed inset-0 z-50 bg-black/80 backdrop-blur-sm flex items-center justify-center p-4">
<div className="bg-neutral-900 border border-purple-500/40 rounded-3xl max-w-lg w-full p-6 space-y-5 shadow-2xl animate-in zoom-in-95">
<div className="flex items-center justify-between border-b border-neutral-800 pb-3">
<h3 className="font-black text-white text-base flex items-center gap-2">
<Edit3 className="w-5 h-5 text-purple-400" />
<span>Personalizar antes de Publicar</span>
</h3>
<button
onClick={() => setEditingPost(null)}
className="text-neutral-400 hover:text-white font-bold"
>
✕
</button>
</div>
<div className="space-y-3.5 text-xs">
<div>
<label className="font-bold text-neutral-300 block mb-1">Nombre Comercial del Modelo:</label>
<input
type="text"
value={editName}
onChange={(e) => setEditName(e.target.value)}
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white font-bold outline-hidden focus:border-purple-500"
/>
</div>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="font-bold text-neutral-300 block mb-1">Marca:</label>
<input
type="text"
value={editBrand}
onChange={(e) => setEditBrand(e.target.value)}
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-500"
/>
</div>
<div>
<label className="font-bold text-emerald-400 block mb-1">Precio de Venta (COP):</label>
<input
type="number"
value={editPrice}
onChange={(e) => setEditPrice(Number(e.target.value))}
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-emerald-300 font-black font-mono outline-hidden focus:border-emerald-500"
/>
</div>
</div>
<div>
<label className="font-bold text-neutral-300 block mb-1">Tallas (separadas por coma):</label>
<input
type="text"
value={editSizes}
onChange={(e) => setEditSizes(e.target.value)}
placeholder="38, 39, 40, 41, 42, 43"
className="w-full bg-neutral-950 border border-neutral-800 rounded-xl px-3 py-2 text-white outline-hidden focus:border-purple-500"
/>
</div>
</div>
<div className="flex items-center gap-2.5 pt-3 border-t border-neutral-800">
<button
onClick={() => setEditingPost(null)}
className="flex-1 bg-neutral-800 hover:bg-neutral-700 text-neutral-300 font-bold text-xs py-3 rounded-xl cursor-pointer"
>
Cancelar
</button>
<button
onClick={() => {
const sizesArray = editSizes
.split(',')
.map((s) => s.trim())
.filter(Boolean);
handlePublishPost(editingPost, {
name: editName,
brand: editBrand,
retailPrice: editPrice,
sizes: sizesArray,
});
}}
className="flex-1 bg-gradient-to-r from-purple-600 to-fuchsia-600 hover:opacity-95 text-white font-black text-xs py-3 rounded-xl shadow-lg shadow-purple-600/30 cursor-pointer"
>
Guardar y Publicar en la App
</button>
</div>
</div>
</div>
)}
</div>
);
}