Add payment modal for reloading credits with simulated payment flow
Some checks failed
continuous-integration/drone/push Build was killed

Integrated a modal to handle credit reloading with a simulated payment process. Updated logic to manage payment amount, successful payment handling, and credit updates. Improved UI with validations and placeholders for future payment gateway integration.
This commit is contained in:
2025-11-22 22:46:35 -04:00
parent 1458c143bc
commit f038fe4c69

View File

@@ -41,17 +41,24 @@ function App() {
setIsMobileMenuOpen(false);
};
const [showPayment, setShowPayment] = useState(false);
const handleReloadCredits = () => {
const input = window.prompt('¿Cuántos créditos desea recargar?');
if (input == null) return;
const add = parseInt(input, 10);
if (Number.isNaN(add) || add <= 0) {
alert('Ingrese un número válido mayor a 0.');
return;
// Abrir modal de pasarela de pago
setShowPayment(true);
};
const handlePaymentClose = () => setShowPayment(false);
const handlePaymentSuccess = (amount) => {
// Actualizar créditos después de un pago exitoso
const add = parseInt(amount, 10);
if (!Number.isNaN(add) && add > 0) {
const next = credits + add;
setCredits(next);
try { localStorage.setItem('credits', String(next)); } catch {}
}
const next = credits + add;
setCredits(next);
try { localStorage.setItem('credits', String(next)); } catch {}
setShowPayment(false);
};
const headerTitle = activeView === 'scheduled'
@@ -68,6 +75,25 @@ function App() {
? 'Perfil'
: 'Dashboard';
const [paymentAmount, setPaymentAmount] = useState('');
const [isPaying, setIsPaying] = useState(false);
const proceedPayment = async () => {
const val = parseInt(paymentAmount, 10);
if (Number.isNaN(val) || val <= 0) {
alert('Ingrese un monto válido mayor a 0.');
return;
}
// Simulación de pasarela de pago
try {
setIsPaying(true);
await new Promise((res) => setTimeout(res, 1200));
handlePaymentSuccess(val);
} finally {
setIsPaying(false);
}
};
return (
<div className="container">
<Sidebar
@@ -99,6 +125,70 @@ function App() {
</div>
</section>
)}
{showPayment && (
<div className="modal-overlay" onClick={handlePaymentClose}>
<div className="modal" onClick={(e) => e.stopPropagation()}>
<div className="modal-header">
<h3>
<i className="fas fa-credit-card"></i>
Recargar créditos
</h3>
<button className="btn btn-outline btn-sm" onClick={handlePaymentClose} disabled={isPaying}>
<i className="fas fa-times"></i> Cerrar
</button>
</div>
<div className="modal-body">
<div className="form-container">
<div className="form-row">
<div className="form-group" style={{ flex: 1 }}>
<label>
<i className="fas fa-coins" aria-hidden="true"></i> Monto a recargar (créditos)
</label>
<input
className="input"
type="number"
min={1}
step={1}
value={paymentAmount}
onChange={(e) => setPaymentAmount(e.target.value)}
placeholder="Ej: 10"
disabled={isPaying}
autoFocus
/>
</div>
</div>
{/* Placeholder de pasarela de pago: reemplace con su integración real (Mercado Pago, Stripe, etc.) */}
<div className="card" style={{ marginTop: 12 }}>
<div className="form-header">
<h3>
<i className="fas fa-shield-alt" style={{ marginRight: 8 }}></i>
Pasarela de pago
</h3>
</div>
<div style={{ padding: 12 }}>
<p style={{ marginTop: 0, color: 'var(--gray)' }}>
Esta es una simulación. Conecte aquí su pasarela (iframe, checkout, etc.).
</p>
<button className="btn btn-primary" onClick={proceedPayment} disabled={isPaying}>
{isPaying ? (
<>
<i className="fas fa-spinner fa-spin"></i> Procesando...
</>
) : (
<>
<i className="fas fa-lock"></i> Pagar y recargar
</>
)}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</main>
</div>
);