- Convert site from royal-blue theme to black/white monochrome (desaturate all blue-hued colors; keep WhatsApp green and error red) - Swap blue circular brand logo for mono YS mark; regenerate favicon/PWA icons - Add 6 Pudu robots (CC1 Pro, MT1 Max, MT1 Vac, T600, T600 Underride, BG1 Pro) - Fix favicon.ico to RGBA (Next 16 Turbopack decode) and Stripe apiVersion type Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
86 lines
2.3 KiB
TypeScript
86 lines
2.3 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
|
|
import { orderStore } from '@/store/useOrderStore';
|
|
|
|
export function PaymentStep() {
|
|
const stripe = useStripe();
|
|
const elements = useElements();
|
|
const [errorMsg, setErrorMsg] = useState('');
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const handleSubmit = async () => {
|
|
if (!stripe || !elements) return;
|
|
|
|
setIsLoading(true);
|
|
setErrorMsg('');
|
|
|
|
// Validate the payment element first
|
|
const { error: submitError } = await elements.submit();
|
|
if (submitError) {
|
|
setErrorMsg(submitError.message || 'Validation failed');
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
// Move to review actual confirmation happens on "Place Order"
|
|
orderStore.getState().setPayment({ status: 'idle' });
|
|
orderStore.getState().setStep('review');
|
|
setIsLoading(false);
|
|
};
|
|
|
|
return (
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
<h3 style={{ fontSize: '1rem', fontWeight: 600, color: '#0b0b0b', margin: 0 }}>
|
|
Payment Details
|
|
</h3>
|
|
|
|
<div style={{
|
|
padding: '1rem',
|
|
borderRadius: '0.5rem',
|
|
background: '#fff',
|
|
border: '1px solid rgba(0, 0, 0, 0.08)',
|
|
}}>
|
|
<PaymentElement
|
|
options={{
|
|
layout: 'tabs',
|
|
}}
|
|
/>
|
|
</div>
|
|
|
|
{errorMsg && (
|
|
<div style={{
|
|
padding: '0.6rem 0.75rem',
|
|
borderRadius: '0.375rem',
|
|
background: 'rgba(239, 68, 68, 0.06)',
|
|
border: '1px solid rgba(239, 68, 68, 0.15)',
|
|
fontSize: '0.75rem',
|
|
color: '#dc2626',
|
|
}}>
|
|
{errorMsg}
|
|
</div>
|
|
)}
|
|
|
|
<button
|
|
onClick={handleSubmit}
|
|
disabled={!stripe || isLoading}
|
|
style={{
|
|
marginTop: '0.5rem',
|
|
padding: '0.75rem',
|
|
borderRadius: '0.375rem',
|
|
border: '1px solid rgba(153, 153, 153, 0.5)',
|
|
background: isLoading ? 'rgba(153, 153, 153, 0.15)' : 'rgba(153, 153, 153, 0.08)',
|
|
color: '#888888',
|
|
cursor: isLoading ? 'wait' : 'pointer',
|
|
fontSize: '0.85rem',
|
|
fontWeight: 600,
|
|
transition: 'all 0.2s ease',
|
|
}}
|
|
>
|
|
{isLoading ? 'Validating...' : 'Review Order'}
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|