Вопрос или проблема
Итак, я пытаюсь сделать так, чтобы выбранные продукты отображались на странице корзины, даже если я выйду из учетной записи, чтобы они оставались в базе данных для соответствующего пользователя. Но я думаю, что проблема в переменной size, которая мешает этому, я пытался добавить, но будучи новичком в react и mongo db, не смог.
Я пытался изменить базу данных, но atlas на моем сайте не обновился…
Код mongo db на данный момент
//Создание API для пользователя
const Users = mongoose.model('Users', {
name:{
type: String,
},
email:{
type: String,
unique:true,
},
password:{
type:String,
},
cartData:{
type:Object,
},
date:{
type:Date,
default:Date.now,
}
})
Я изменил это на следующее на своей стороне сервера
const Users = mongoose.model('Users', {
name: {
type: String,
},
email: {
type: String,
unique: true,
},
password: {
type: String,
},
cartData: {
type: Map,
of: {
type: Object,
default: {
S: { type: Number, default: 0 },
M: { type: Number, default: 0 },
L: { type: Number, default: 0 },
XL: { type: Number, default: 0 },
XXL: { type: Number, default: 0 },
},
},
},
date: {
type: Date,
default: Date.now,
},
});
Мое API для добавления в корзину
// Точка доступа для добавления продуктов в данные корзины
app.post('/addtocart', fetchUser, async (req, res) => {
console.log("добавлено", req.body.jerseyId);
try {
const { jerseyId } = req.body;
if (!jerseyId) {
return res.status(400).json({ error: "ID товара необходим" });
}
let userData = await Users.findOne({ _id: req.user.id });
// Инициализировать элемент в корзине, если его нет
if (!userData.cartData[jerseyId]) {
userData.cartData[jerseyId] = 0;
}
userData.cartData[jerseyId] += 1;
await Users.findOneAndUpdate({ _id: req.user.id }, { cartData: userData.cartData });
res.json({ success: true, message: "Товар успешно добавлен в корзину" });
} catch (error) {
console.error("Ошибка при добавлении товара в корзину:", error);
res.status(500).json({ success: false, message: "Произошла ошибка при добавлении товара в корзину" });
}
});
фронтенд, который вызывает API
const addToCart = (jerseyId, size) => {
setCartItems((prev) => ({
...prev,
[jerseyId]: {
...prev[jerseyId],
[size]: (prev[jerseyId][size] || 0) + 1, // Увеличить количество для выбранного размера
},
}));
if (localStorage.getItem('auth-token')) {
fetch('http://localhost:4000/addtocart', {
method: 'POST',
headers: {
Accept: 'application/json',
'auth-token': localStorage.getItem('auth-token'),
'Content-Type': 'application/json',
},
body: JSON.stringify({ jerseyId, size }), // Теперь отправляем как jerseyId, так и size
})
.then(response => response.json())
.then(data => console.log(data));
}
};
Как выглядит страница корзины (на всякий случай)
import React, { useContext } from 'react';
import './CartItems.css'; // Импорт CSS файла для стилизации.
import { ShopContext } from '../../Context/ShopContext'; // Импорт ShopContext для доступа к функциям и данным, связанным с корзиной.
import remove_icon from '../Assets/remove_icon.jpg'; // Иконка удаления товара.
const CartItems = () => {
const { getTotalCartAmount, every_product, cartItems, removeFromCart } = useContext(ShopContext); // Доступ к контексту корзины.
return (
<div className="cartitems">
{/* Заголовок для деталей товара в корзине */}
<div className="cartitems-format-main">
<p>Продукты</p>
<p>Название</p>
<p>Размер</p> {/* Добавлен столбец Размер */}
<p>Цена</p>
<p>Количество</p>
<p>Итого</p>
{/* <p>Удалить</p> */}
</div>
<hr />
{/* Отображение каждого товара в корзине */}
{every_product.map((e) => {
// Проверка, есть ли какой-либо товар этого продукта в корзине для любого размера
const productInCart = Object.keys(cartItems[e.id]).filter(size => cartItems[e.id][size] > 0);
// Отображаем только продукты с количеством больше 0 для любого размера
return productInCart.length > 0 ? (
<div key={e.id}>
{productInCart.map((size) => (
<div className="cartitems-format cartitems-format-main" key={size}>
{/* Изображение продукта */}
<img
src={e.image || 'default_image_path.jpg'}
alt={e.name}
className="carticon-product-icon"
/>
<p>{e.name}</p> {/* Название продукта */}
<p>{size}</p> {/* Отображение выбранного размера */}
<p>${e.us_cost}</p> {/* Цена продукта */}
{/* Кнопка количества */}
<button className="cart-items-quantity">
{cartItems[e.id][size]} {/* Отображение количества для выбранного размера */}
</button>
{/* Общая цена для продукта на основе количества и размера */}
<p>${e.us_cost * cartItems[e.id][size]}</p>
{/* Кнопка удаления из корзины */}
<img
src={remove_icon}
onClick={() => removeFromCart(e.id, size)}
alt="Удалить товар"
className="cart-items-remove-icon"
/>
</div>
))}
<hr />
</div>
) : null; // Явно возвращаем null, если для этого продукта нет товаров
})}
{/* Раздел для общей суммы корзины и оформления заказа */}
<div className="cart-items-down">
<div className="cartitems-total">
<h1>Итого</h1>
<div>
{/* Промежуточный итог */}
<div className="cartitems-total-item">
<p>Промежуточный итог</p>
<p>${getTotalCartAmount()}</p> {/* Общая стоимость всех товаров в корзине */}
</div>
<hr />
{/* Доставка */}
<div className="cartitems-total-item">
<p>Доставка</p>
<p>Бесплатная доставка!</p>
</div>
<hr />
{/* Общая сумма */}
<div className="cartitems-total-item">
<h3>Итого</h3>
<h3>${getTotalCartAmount()}</h3> {/* Общая сумма после доставки */}
</div>
</div>
{/* Кнопка перехода к оформлению заказа */}
<button className="cart-items-checkout-button">ПЕРЕЙТИ К ОФОРМЛЕНИЮ ЗАКАЗА</button>
</div>
</div>
</div>
);
};
export default CartItems;
Ответ или решение
Проблема с сохраняемостью товаров в корзине при выходе из аккаунта в React E-commerce
Ваша проблема заключается в том, что выбранные товары в корзине не сохраняются для пользователя после выхода из его аккаунта. Этот функционал является важным аспектом для e-commerce приложений, так как он обеспечивает удобство и непрерывность пользовательского опыта. Давайте рассмотрим, как вы можете это исправить.
Анализ текущей архитектуры
На данный момент ваш код показывает, что корзина пользователя хранится в базе данных MongoDB в поле cartData
объекта Users
. Ваша попытка изменить структуру этого поля с простого объекта на Map
, содержащий различные размеры одежды, является шагом в правильном направлении. Однако необходимо убедиться, что данные корректно сохраняются и извлекаются из базы.
-
Обновление структуры данных.
- Убедитесь, что обновление поля
cartData
происходит без ошибок. Смотрите, не возникает ли никаких исключений при обновлении. Логирование ошибок может помочь идентифицировать проблемы.
- Убедитесь, что обновление поля
-
Корректное сохранение размеров.
- Вам нужно удостовериться, что при добавлении товара в корзину вы не только увеличиваете количество, но и правильно сохраняете размер. В текущем коде при вызове API добавления в корзину вы передаете
jerseyId
, ноsize
не сохраняется в полеcartData
. Вам нужно хранить информацию о размере, чтобы пользователь мог ее видеть позже.
- Вам нужно удостовериться, что при добавлении товара в корзину вы не только увеличиваете количество, но и правильно сохраняете размер. В текущем коде при вызове API добавления в корзину вы передаете
Исправление кода
-
Модификация API для добавления в корзину:
app.post('/addtocart', fetchUser, async (req, res) => { const { jerseyId, size } = req.body; if (!jerseyId || !size) { return res.status(400).json({ error: "Item ID and size are required" }); } try { const userData = await Users.findOne({ _id: req.user.id }); // Инициализация товара в корзине, если он не существует if (!userData.cartData[jerseyId]) { userData.cartData[jerseyId] = { S: 0, M: 0, L: 0, XL: 0, XXL: 0 }; // Пример инициализации } userData.cartData[jerseyId][size] += 1; // Увеличиваем количество для конкретного размера await Users.findOneAndUpdate({ _id: req.user.id }, { cartData: userData.cartData }); res.json({ success: true, message: "Item added to cart successfully" }); } catch (error) { console.error("Error adding item to cart:", error); res.status(500).json({ success: false, message: "An error occurred while adding the item to the cart" }); } });
-
Обновление функционала фронтенда:
В методеaddToCart
, убедитесь, что вы передаете иsize
, иjerseyId
, как это и сделано в вашем примере. Убедитесь, что сервер корректно воспринимает оба параметра и возвращает соответствующий ответ.const addToCart = (jerseyId, size) => { setCartItems(prev => ({ ...prev, ...prev[jerseyId], [size]: (prev[jerseyId][size] || 0) + 1, }, })); if (localStorage.getItem('auth-token')) { fetch('http://localhost:4000/addtocart', { method: 'POST', headers: { Accept: 'application/json', 'auth-token': localStorage.getItem('auth-token'), 'Content-Type': 'application/json', }, body: JSON.stringify({ jerseyId, size }), }) .then(response => response.json()) .then(data => console.log(data)); } };
Проверка и тестирование
После внесения изменений обязательно протестируйте:
- Добавление в корзину: Проверьте, что товары корректно добавляются в корзину и сохраняются в базе данных.
- Выход из аккаунта: Попробуйте выйти из аккаунта и снова войти. Корзина должна запомниться.
- Ошибки: Посмотрите в логах на наличие ошибок, которые могут возникнуть при выполнении операций с базой данных.
Заключение
Убедитесь, что данные корректно сохраняются и извлекаются из вашей базы данных. Правильное использование структуры данных поможет вам избежать потенциальных ошибок. Настройка API и фронтенд-кода для обеспечения сохранности информации о размерах товаров в корзине – это ключ к успешному управлению корзиной пользователя.
Эти изменения не только улучшат функциональность вашего приложения, но и создадут приятный опыт для конечного пользователя. Вы сможете повысить лояльность клиентов и увеличить их удовлетворенность.