fixed cart desync
This commit is contained in:
parent
202e99b12f
commit
c913b09edf
6 changed files with 54 additions and 25 deletions
|
|
@ -52,7 +52,7 @@ const upload = multer({
|
|||
storage,
|
||||
fileFilter,
|
||||
limits: {
|
||||
fileSize: 5 * 1024 * 1024 // 5MB limit
|
||||
fileSize: 10 * 1024 * 1024 // 10MB
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ const createTransporter = () => {
|
|||
});
|
||||
};
|
||||
|
||||
// Mock email transporter for development
|
||||
const transporter = createTransporter();
|
||||
|
||||
module.exports = (pool, query) => {
|
||||
|
|
@ -94,7 +93,6 @@ module.exports = (pool, query) => {
|
|||
[authId, user.id]
|
||||
);
|
||||
|
||||
// Send email with code (mock in development)
|
||||
const loginLink = `${config.site.protocol}://${config.site.domain}/verify?code=${authCode}&email=${encodeURIComponent(email)}`;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -513,7 +513,6 @@ module.exports = (pool, query, authMiddleware) => {
|
|||
? shippingService.parseAddressString(shippingAddress)
|
||||
: shippingAddress;
|
||||
|
||||
console.log("Fetching rates for parsed address:", parsedAddress);
|
||||
|
||||
const shippingResponse = await shippingService.getShippingRates(
|
||||
null, // Use default from config
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { loadStripe } from '@stripe/stripe-js';
|
|||
import { Elements } from '@stripe/react-stripe-js';
|
||||
import config from '../config';
|
||||
import apiClient from '@services/api';
|
||||
import { useAuth } from '@hooks/reduxHooks';
|
||||
|
||||
// Create the context
|
||||
const StripeContext = createContext();
|
||||
|
|
@ -12,13 +13,19 @@ export const StripeProvider = ({ children }) => {
|
|||
const [clientSecret, setClientSecret] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
const { isAuthenticated } = useAuth();
|
||||
|
||||
// Load or reload Stripe configuration when authentication state changes
|
||||
useEffect(() => {
|
||||
// Reset state when auth changes
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Try to load Stripe public key from environment
|
||||
let publicKey = import.meta.env.VITE_STRIPE_PUBLIC_KEY;
|
||||
|
||||
// If not found, fetch from API
|
||||
if (!publicKey) {
|
||||
if (isAuthenticated) {
|
||||
// Fetch Stripe public key from backend
|
||||
apiClient.get('/payment/config')
|
||||
.then(response => {
|
||||
|
|
@ -34,10 +41,10 @@ export const StripeProvider = ({ children }) => {
|
|||
setError('Failed to load payment configuration');
|
||||
setIsLoading(false);
|
||||
});
|
||||
} else {
|
||||
} else if(publicKey){
|
||||
loadStripeInstance(publicKey);
|
||||
}
|
||||
}, []);
|
||||
}, [isAuthenticated]); // Add isAuthenticated as a dependency to reload on auth changes
|
||||
|
||||
const loadStripeInstance = (publicKey) => {
|
||||
try {
|
||||
|
|
@ -102,7 +109,27 @@ export const StripeProvider = ({ children }) => {
|
|||
error,
|
||||
createCheckoutSession,
|
||||
checkSessionStatus,
|
||||
completeOrder
|
||||
completeOrder,
|
||||
reloadConfig: () => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
if (isAuthenticated){
|
||||
apiClient.get('/payment/config')
|
||||
.then(response => {
|
||||
if (response.data.stripePublicKey) {
|
||||
loadStripeInstance(response.data.stripePublicKey);
|
||||
} else {
|
||||
setError('Stripe public key not found');
|
||||
setIsLoading(false);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error fetching Stripe config:', err);
|
||||
setError('Failed to load payment configuration');
|
||||
setIsLoading(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import apiClient from '../../services/api';
|
|||
import { useAdminCategories } from '../../hooks/categoryAdminHooks';
|
||||
|
||||
const AdminDashboardPage = () => {
|
||||
// Mock data - would be replaced with real API calls
|
||||
const [stats, setStats] = useState({
|
||||
totalProducts: 0,
|
||||
totalUsers: 0,
|
||||
|
|
@ -53,7 +52,6 @@ const AdminDashboardPage = () => {
|
|||
// Fetch categories
|
||||
const { data: categories, isLoading: categoriesLoading } = useAdminCategories();
|
||||
|
||||
// Mock recent orders - would be replaced with real API data
|
||||
const recentOrders = [
|
||||
{ id: '4532', customer: 'John Doe', date: '2023-04-22', total: 49.99, status: 'Delivered' },
|
||||
{ id: '4531', customer: 'Jane Smith', date: '2023-04-21', total: 89.95, status: 'Processing' },
|
||||
|
|
@ -67,10 +65,9 @@ const AdminDashboardPage = () => {
|
|||
setStats(prev => ({
|
||||
...prev,
|
||||
totalProducts: products.length,
|
||||
// Other stats would be updated from their respective API calls
|
||||
totalUsers: 15, // Mock data
|
||||
totalOrders: 42, // Mock data
|
||||
revenue: 2459.99 // Mock data
|
||||
totalUsers: 15,
|
||||
totalOrders: 42,
|
||||
revenue: 2459.99
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ import {
|
|||
FormLabel
|
||||
} from '@mui/material';
|
||||
import { useNavigate, Link as RouterLink } from 'react-router-dom';
|
||||
import { useAuth, useCart } from '../hooks/reduxHooks';
|
||||
import { useCheckout } from '../hooks/apiHooks';
|
||||
import { useAuth } from '../hooks/reduxHooks';
|
||||
import { useCheckout, useGetCart } from '../hooks/apiHooks';
|
||||
import { useStripe, StripeElementsProvider } from '../context/StripeContext';
|
||||
import apiClient from '../services/api';
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ const steps = ['Shipping Address', 'Shipping Method', 'Review Order', 'Payment',
|
|||
const CheckoutPage = () => {
|
||||
const navigate = useNavigate();
|
||||
const { user, userData } = useAuth();
|
||||
const { items, total, itemCount } = useCart();
|
||||
const { data: cart, isLoading: cartLoading } = useGetCart(user);
|
||||
const checkout = useCheckout();
|
||||
const { createCheckoutSession, isLoading: isStripeLoading } = useStripe();
|
||||
|
||||
|
|
@ -54,8 +54,8 @@ const CheckoutPage = () => {
|
|||
|
||||
// State for form data
|
||||
const [formData, setFormData] = useState({
|
||||
firstName: userData?.first_name || '',
|
||||
lastName: userData?.last_name || '',
|
||||
firstName: userData?.firstName || '',
|
||||
lastName: userData?.lastName || '',
|
||||
email: userData?.email || '',
|
||||
address: '',
|
||||
city: '',
|
||||
|
|
@ -125,7 +125,6 @@ const CheckoutPage = () => {
|
|||
|
||||
for (const field of requiredFields) {
|
||||
if (!formData[field]) {
|
||||
// In a real app, you'd set specific errors for each field
|
||||
setError(`Please fill in all required fields`);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -210,7 +209,7 @@ const CheckoutPage = () => {
|
|||
|
||||
// Handle place order
|
||||
const handlePlaceOrder = async () => {
|
||||
if (!user || !items || items.length === 0) {
|
||||
if (!user || !cart || !cart.items || cart.items.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -280,8 +279,17 @@ const CheckoutPage = () => {
|
|||
}
|
||||
}, [checkoutUrl]);
|
||||
|
||||
// Loading state
|
||||
if (cartLoading) {
|
||||
return (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', my: 8 }}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// If no items in cart, redirect to cart page
|
||||
if (!items || items.length === 0) {
|
||||
if (!cart || !cart.items || cart.items.length === 0) {
|
||||
return (
|
||||
<Box sx={{ textAlign: 'center', py: 6 }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
|
|
@ -489,7 +497,7 @@ const CheckoutPage = () => {
|
|||
</Typography>
|
||||
|
||||
<List disablePadding>
|
||||
{items.map((item) => (
|
||||
{cart.items.map((item) => (
|
||||
<ListItem key={item.product_id} sx={{ py: 1, px: 0 }}>
|
||||
<ListItemText
|
||||
primary={item.name}
|
||||
|
|
@ -503,7 +511,7 @@ const CheckoutPage = () => {
|
|||
|
||||
<ListItem sx={{ py: 1, px: 0 }}>
|
||||
<ListItemText primary="Subtotal" />
|
||||
<Typography variant="body2">${total.toFixed(2)}</Typography>
|
||||
<Typography variant="body2">${cart.subtotal.toFixed(2)}</Typography>
|
||||
</ListItem>
|
||||
|
||||
<ListItem sx={{ py: 1, px: 0 }}>
|
||||
|
|
@ -519,7 +527,7 @@ const CheckoutPage = () => {
|
|||
<ListItem sx={{ py: 1, px: 0 }}>
|
||||
<ListItemText primary="Total" />
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
|
||||
${(total + shippingCost).toFixed(2)}
|
||||
${(cart.subtotal + shippingCost).toFixed(2)}
|
||||
</Typography>
|
||||
</ListItem>
|
||||
</List>
|
||||
|
|
|
|||
Loading…
Reference in a new issue