Feat: Cambios Varios

This commit is contained in:
2025-12-23 15:12:57 -03:00
parent 32663e6324
commit 8bc1308bc5
58 changed files with 4080 additions and 663 deletions

View File

@@ -3,11 +3,13 @@ import { useWizardStore } from '../../store/wizardStore';
import { wizardService } from '../../services/wizardService';
import { StepWrapper } from '../../components/StepWrapper';
import type { AttributeDefinition } from '../../types';
import { CreditCard, Wallet } from 'lucide-react';
export default function SummaryStep({ definitions }: { definitions: AttributeDefinition[] }) {
const { selectedCategory, selectedOperation, attributes, setStep } = useWizardStore();
const { selectedCategory, selectedOperation, attributes, photos, setStep } = useWizardStore();
const [isSubmitting, setIsSubmitting] = useState(false);
const [createdId, setCreatedId] = useState<number | null>(null);
const [paymentMethod, setPaymentMethod] = useState<'mercadopago' | 'stripe'>('mercadopago');
const handlePublish = async () => {
if (!selectedCategory || !selectedOperation) return;
@@ -15,37 +17,36 @@ export default function SummaryStep({ definitions }: { definitions: AttributeDef
setIsSubmitting(true);
try {
const attributePayload: Record<number, string> = {};
// Ideally we should have stored definitions in store or passed them.
// For now assuming 'definitions' prop contains current category definitions
// For now assuming 'definitions' prop contains current category definitions
definitions.forEach(def => {
if (attributes[def.name]) {
attributePayload[def.id] = attributes[def.name].toString();
}
});
// Crear aviso con estado PENDING (Esperando pago)
const payload = {
categoryId: selectedCategory.id,
operationId: selectedOperation.id,
title: attributes['title'],
description: 'Generated via Wizard', // Todo: Add description field
description: 'Generated via Wizard',
price: parseFloat(attributes['price']),
currency: 'ARS',
status: 'Pending', // <-- Importante para moderación
attributes: attributePayload
};
const result = await wizardService.createListing(payload);
// Upload Images
const { photos } = useWizardStore.getState();
if (photos.length > 0) {
for (const photo of photos) {
await wizardService.uploadImage(result.id, photo);
}
}
// Simulación de Pago
await new Promise(resolve => setTimeout(resolve, 2000)); // Fake network delay
setCreatedId(result.id);
} catch (error) {
console.error(error);
@@ -58,11 +59,16 @@ export default function SummaryStep({ definitions }: { definitions: AttributeDef
if (createdId) {
return (
<StepWrapper>
<div className="text-center py-10">
<div className="text-4xl text-green-500 mb-4"></div>
<h2 className="text-2xl font-bold mb-2">¡Aviso Publicado!</h2>
<p className="text-gray-500">ID de referencia: #{createdId}</p>
<button onClick={() => window.location.reload()} className="mt-8 text-brand-600 underline">Publicar otro</button>
<div className="text-center py-10 bg-white rounded-xl shadow p-8 border border-green-100">
<div className="text-6xl text-green-500 mb-4 animate-bounce"></div>
<h2 className="text-3xl font-bold mb-2 text-gray-800">¡Pago Exitoso!</h2>
<p className="text-gray-500 text-lg">Tu aviso #{createdId} ha sido enviado a moderación.</p>
<div className="mt-8 p-4 bg-gray-50 rounded text-sm text-gray-600">
Comprobante de pago: {paymentMethod === 'mercadopago' ? 'MP-123456789' : 'ST-987654321'}
</div>
<button onClick={() => window.location.reload()} className="mt-8 bg-brand-600 text-white px-6 py-3 rounded-lg font-bold hover:bg-brand-700 transition">
Publicar otro aviso
</button>
</div>
</StepWrapper>
);
@@ -70,48 +76,62 @@ export default function SummaryStep({ definitions }: { definitions: AttributeDef
return (
<StepWrapper>
<h2 className="text-2xl font-bold mb-6 text-brand-900">Resumen y Confirmación</h2>
<h2 className="text-2xl font-bold mb-6 text-brand-900">Resumen y Pago</h2>
<div className="bg-white p-6 rounded-xl border border-slate-200 shadow-sm mb-6">
<div className="mb-4">
<span className="block text-xs text-slate-500 uppercase tracking-wide">Categoría</span>
<span className="font-semibold text-lg">{selectedCategory?.name}</span>
</div>
<div className="mb-4">
<span className="block text-xs text-slate-500 uppercase tracking-wide">Operación</span>
<span className="font-semibold text-lg">{selectedOperation?.name}</span>
</div>
<div className="border-t pt-4 mt-4">
<h3 className="font-bold mb-2">{attributes['title']}</h3>
<div className="text-2xl font-bold text-green-600 mb-4">$ {attributes['price']}</div>
<div className="grid grid-cols-2 gap-2 text-sm">
{definitions.map(def => attributes[def.name] && (
<div key={def.id}>
<span className="text-slate-500">{def.name}:</span> <span className="font-medium">{attributes[def.name]}</span>
</div>
))}
<div className="flex justify-between items-center mb-4 border-b pb-4">
<div>
<span className="block text-xs text-slate-500 uppercase tracking-wide">Categoría</span>
<span className="font-semibold text-lg">{selectedCategory?.name}</span>
</div>
<div className="text-right">
<span className="block text-xs text-slate-500 uppercase tracking-wide">Operación</span>
<span className="font-semibold text-lg">{selectedOperation?.name}</span>
</div>
</div>
<h3 className="font-bold mb-2 text-xl">{attributes['title']}</h3>
<div className="text-3xl font-bold text-green-600 mb-6">$ {attributes['price']}</div>
<div className="grid grid-cols-2 gap-3 text-sm bg-gray-50 p-4 rounded-lg">
{definitions.map(def => attributes[def.name] && (
<div key={def.id}>
<span className="text-slate-500 font-medium">{def.name}:</span> <span className="text-slate-800">{attributes[def.name]}</span>
</div>
))}
</div>
</div>
{/* Selector de Pago */}
<div className="mb-8">
<h3 className="font-bold text-gray-800 mb-3 text-lg">Selecciona Método de Pago</h3>
<div className="grid grid-cols-2 gap-4">
<label className={`flex items-center gap-3 p-4 rounded-xl border-2 cursor-pointer transition-all ${paymentMethod === 'mercadopago' ? 'border-blue-500 bg-blue-50' : 'border-gray-200 bg-white hover:border-blue-200'}`}>
<input type="radio" name="payment" value="mercadopago" checked={paymentMethod === 'mercadopago'} onChange={() => setPaymentMethod('mercadopago')} className="hidden" />
<div className="bg-blue-100 p-2 rounded-full text-blue-600"><Wallet size={24} /></div>
<div>
<div className="font-bold text-gray-800">Mercado Pago</div>
<div className="text-xs text-gray-500">QR, Débito, Crédito</div>
</div>
</label>
<label className={`flex items-center gap-3 p-4 rounded-xl border-2 cursor-pointer transition-all ${paymentMethod === 'stripe' ? 'border-indigo-500 bg-indigo-50' : 'border-gray-200 bg-white hover:border-indigo-200'}`}>
<input type="radio" name="payment" value="stripe" checked={paymentMethod === 'stripe'} onChange={() => setPaymentMethod('stripe')} className="hidden" />
<div className="bg-indigo-100 p-2 rounded-full text-indigo-600"><CreditCard size={24} /></div>
<div>
<div className="font-bold text-gray-800">Tarjeta Crédito</div>
<div className="text-xs text-gray-500">Procesado por Stripe</div>
</div>
</label>
</div>
</div>
<div className="flex gap-4">
<button
onClick={() => setStep(3)}
className="flex-1 py-3 text-slate-600 hover:bg-slate-100 rounded-lg"
disabled={isSubmitting}
>
Volver
</button>
<button
onClick={handlePublish}
disabled={isSubmitting}
className="flex-1 py-3 bg-brand-600 text-white font-bold rounded-lg hover:bg-brand-700 disabled:opacity-50"
>
{isSubmitting ? 'Publicando...' : 'Confirmar y Publicar'}
<button onClick={() => setStep(4)} className="px-6 py-3 text-slate-600 hover:bg-slate-100 rounded-lg font-medium" disabled={isSubmitting}>Volver</button>
<button onClick={handlePublish} disabled={isSubmitting} className="flex-1 py-3 bg-brand-600 text-white font-bold rounded-xl hover:bg-brand-700 disabled:opacity-70 disabled:cursor-not-allowed shadow-lg shadow-brand-200 transition-all text-lg">
{isSubmitting ? 'Procesando pago...' : 'Pagar y Publicar'}
</button>
</div>
</StepWrapper>
);
}
}