0% found this document useful (0 votes)
44 views5 pages

Message

The document is a React functional component named PixPayment that handles the payment process using the Pix payment system. It includes features such as a countdown timer, QR code loading, and the ability to copy the Pix code. The component also displays order details and allows users to confirm their payment with a button.

Uploaded by

iframecsgo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views5 pages

Message

The document is a React functional component named PixPayment that handles the payment process using the Pix payment system. It includes features such as a countdown timer, QR code loading, and the ability to copy the Pix code. The component also displays order details and allows users to confirm their payment with a button.

Uploaded by

iframecsgo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

import React, { useState, useEffect } from 'react';

import { ChevronLeft, Copy, Clock, Check } from 'lucide-react';

interface PixPaymentProps {
total: number;
orderNumber: string;
restaurantName: string;
restaurantLogo: string;
pixCode?: string;
paymentId?: string;
pixImageUrl?: string;
onBack: () => void;
}

const PixPayment: React.FC<PixPaymentProps> = ({


total,
orderNumber,
restaurantName,
restaurantLogo,
pixCode = '00020101021226900014br.gov.bcb.pix2568pix.ady...',
paymentId,
pixImageUrl,
onBack
}) => {
const [timeLeft, setTimeLeft] = useState(10 * 60); // 24 hours in seconds (1 day)
const [copied, setCopied] = useState(false);
const [loadingQrCode, setLoadingQrCode] = useState(false);
const [isMobile, setIsMobile] = useState(false);

// Check if device is mobile


useEffect(() => {
const checkIfMobile = () => {
setIsMobile(window.innerWidth < 768); // Less than 768px is considered mobile
};

// Check initially
checkIfMobile();

// Add event listener for window resize


window.addEventListener('resize', checkIfMobile);

// Cleanup
return () => window.removeEventListener('resize', checkIfMobile);
}, []);

// Se recebermos um novo pixCode, resetamos o timer


useEffect(() => {
if (pixCode) {
setTimeLeft(10 * 60); // 24 horas
}
}, [pixCode]);

useEffect(() => {
if (timeLeft > 0) {
const timer = setInterval(() => {
setTimeLeft(prev => prev - 1);
}, 1000);
return () => clearInterval(timer);
}
}, [timeLeft]);

useEffect(() => {
if (pixImageUrl) {
setLoadingQrCode(true);
const img = new Image();
img.onload = () => {
setLoadingQrCode(false);
};
img.onerror = () => {
setLoadingQrCode(false);
};
img.src = pixImageUrl;
}
}, [pixImageUrl]);

const formatTime = (seconds: number) => {


if (seconds > 3600) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2,
'0')}`;
} else {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${String(minutes).padStart(2, '0')}:$
{String(remainingSeconds).padStart(2, '0')}`;
}
};

const handleCopyCode = async () => {


try {
await navigator.clipboard.writeText(pixCode);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (err) {
console.error('Failed to copy:', err);
}
};

// O evento InitiateCheckout está agora no CheckoutPage e o Purchase também

return (
<div className="min-h-screen bg-gray-50">
<div className="bg-white p-4 sticky top-0 z-10 border-b border-gray-100">
<div className="flex items-center gap-3">
<button
onClick={onBack}
className="text-red-500"
aria-label="Voltar"
>
<ChevronLeft size={24} />
</button>
<h1 className="text-xl font-semibold text-center flex-1">PAGAMENTO</h1>
<button className="text-red-500 font-medium">Ajuda</button>
</div>
</div>

<div className="p-4 flex flex-col items-center">


{!isMobile && pixImageUrl ? (
<div className="w-64 h-64 flex items-center justify-center mb-6 bg-white
p-4 rounded-lg shadow-sm">
{loadingQrCode ? (
<div className="animate-pulse flex flex-col items-center justify-
center">
<div className="w-48 h-48 bg-gray-200 rounded-md"></div>
<div className="mt-4 text-sm text-gray-500">Carregando QR
Code...</div>
</div>
) : (
<img src={pixImageUrl} alt="QR Code PIX" className="w-full h-full" />
)}
</div>
) : !isMobile ? (
<div className="w-48 h-48 bg-red-50 rounded-full flex items-center
justify-center mb-6">
<svg className="w-24 h-24" viewBox="0 0 48 48">
<path fill="#4db6ac" d="M11.9,12h-0.68l8.04-8.04c2.62-2.61,6.86-
2.61,9.48,0L36.78,12H36.1c-1.6,0-3.11,0.62-4.24,1.76 l-6.8,6.77c-0.59,0.59-
1.53,0.59-2.12,0l-6.8-6.77C15.01,12.62,13.5,12,11.9,12z"></path>
<path fill="#4db6ac" d="M36.1,36h0.68l-8.04,8.04c-2.62,2.61-
6.86,2.61-9.48,0L11.22,36h0.68c1.6,0,3.11-0.62,4.24-1.76 l6.8-6.77c0.59-0.59,1.53-
0.59,2.12,0l6.8,6.77C32.99,35.38,34.5,36,36.1,36z"></path>
<path fill="#4db6ac" d="M44.04,28.74L38.78,34H36.1c-1.07,0-2.07-0.42-
2.83-1.17l-6.8-6.78c-1.36-1.36-3.58-1.36-4.94,0 l-
6.8,6.78C13.97,33.58,12.97,34,11.9,34H9.22l-5.26-5.26c-2.61-2.62-2.61-6.86,0-
9.48L9.22,14h2.68c1.07,0,2.07,0.42,2.83,1.17
l6.8,6.78c0.68,0.68,1.58,1.02,2.47,1.02s1.79-0.34,2.47-1.02l6.8-
6.78C34.03,14.42,35.03,14,36.1,14h2.68l5.26,5.26
C46.65,21.88,46.65,26.12,44.04,28.74z"></path>
</svg>
</div>
) : null}

<h2 className="text-2xl font-bold text-center mb-2">Pedido aguardando


pagamento</h2>
<p className="text-center text-gray-600 mb-8 max-w-md">
Copie o código abaixo e utilize o Pix Copia e Cola no aplicativo que você
vai fazer o pagamento:
</p>

<div className="w-full max-w-md bg-gray-50 p-4 rounded-lg mb-6 relative">


<p className="font-mono text-sm break-all pr-10">{pixCode}</p>
<button
onClick={handleCopyCode}
className="absolute right-2 top-1/2 transform -translate-y-1/2 text-
red-500"
aria-label="Copiar código"
>
{copied ? <Check size={20} className="text-green-500" /> : <Copy
size={20} />}
</button>
</div>

<div className="w-full max-w-md">


<button
onClick={handleCopyCode}
style={{ backgroundColor: '#EA1D2C' }}
className="w-full bg-red-500 text-white py-4 rounded-lg font-medium mt-
4 mb-4 hover:bg-red-600 transition-colors"
>
{copied ? (
<div className="flex items-center justify-center gap-2">
<Check size={18} />
Código copiado!
</div>
) : (
<div className="flex items-center justify-center gap-2">
<Copy size={18} />
Copiar código PIX
</div>
)}
</button>
</div>

<div className="flex items-center gap-2 mb-4 mt-8">


<Clock size={20} className="text-gray-400" />
<p className="text-gray-500">O tempo para você pagar acaba em:</p>
</div>

<div className="text-4xl font-bold mb-12">{formatTime(timeLeft)}</div>

<div className="w-full max-w-md">


<h3 className="text-center text-red-500 font-medium mb-4">Detalhes do
Pedido</h3>

<div className="bg-white rounded-lg p-4 shadow-sm">


<div className="flex items-center gap-3 mb-2">
<img
src={restaurantLogo}
alt={restaurantName}
className="w-12 h-12 rounded-full object-cover"
/>
<div>
<h4 className="font-medium">{restaurantName}</h4>
<p className="text-gray-500 text-sm">Nº do pedido {orderNumber}</p>
{paymentId && (
<p className="text-gray-500 text-sm">ID do pagamento:
{paymentId}</p>
)}
</div>
</div>

<div className="flex justify-between items-center mt-4 pt-4 border-t


border-gray-100">
<span className="font-medium">Total</span>
<span className="font-medium">R$ {total.toFixed(2)}</span>
</div>
</div>

{/* Botão de confirmação para feedback do usuário, sem disparo do evento


Purchase (já está no checkout) */}
<button
onClick={() => {
alert('Obrigado pela sua compra! Em breve seu pedido será
confirmado.');
}}
className="w-full bg-green-500 text-white py-4 rounded-lg font-medium
mt-4 hover:bg-green-600 transition-colors"
>
Confirmei o pagamento
</button>
</div>
</div>
</div>
);
};

export default PixPayment;

You might also like