首页 > 解决方案 > 如何增加/减少购物车中产品的数量?

问题描述

我在实现从购物车中添加或删除产品的逻辑时遇到了一些困难。

首先在我的数据库级别:

这意味着用户实际上有“几个篮子”(一个产品=一个篮子)

后端

以下是我如何使用 sequelize 创建模型/关系:

// Inside db.config.js 
db.paniers = sequelize.define('panier', {
   id: {
      type: Sequelize.INTEGER,
      primaryKey: true,
      autoIncrement: true,
      field: 'PAN_ID'
  },
   userId: {
      type: Sequelize.INTEGER,
      references: {
         model: db.users,
         key: 'USE_ID'
      },
      primaryKey: true,
      allowNull: false,
      field: 'USE_ID'
   },
   produitId : {
      type: Sequelize.INTEGER,
      references: {
         model: db.produits,
         key: 'PRO_ID'
      },
      primaryKey: true,
      allowNull: false,
      field: 'PRO_ID'
   },
   quantite: {
      type: Sequelize.INTEGER,
      allowNull: false,
      field: 'PAN_QUANTITE'
   }
}, {
   tableName: 'PANIER'
});

然后对于查询,进行两个查询:

这是我在 POSTMAN 下进行 axios 查询和结果的方式

const APIURL = 'http://localhost:8090/api';

// Get the details of the cart
export const getDetails = (userId) => axios.get(`${APIURL}/panier/details/${userId}`,
{
    userId: userId,
});

// Update the quantity of the cart
export const updateQuantite = (produitId) => axios.put(`${APIURL}/panier/${produitId}`, 
{
    produitId: produitId,
});

    // Result for the userId 1 (getDetails)
    {
        "PRO_ID": 1,
        "PRO_NOM": "Un immeuble",
        "PRO_PRIX": "1515",
        "PRO_URL": "58afa4f2-41b1-42f7-a371-6d267784c44e.jpg",
        "PAN_QUANTITE": 1,
        "PAN_ID": 1
    },
    {
        "PRO_ID": 2,
        "PRO_NOM": "Model",
        "PRO_PRIX": "102",
        "PRO_URL": "a76fbe76-a183-49fa-84ee-40d5da08b91f.png",
        "PAN_QUANTITE": 1,
        "PAN_ID": 2
    }
    
    

这是我的两个控制器管理他的路线:

// Display the informations of the basket
exports.getDetails = (req, res) => {
    const queryResult = db.sequelize.query(
      'SELECT P.PRO_ID, PRO_NOM, PRO_PRIX, PRO_URL, PA.PAN_QUANTITE, PA.PAN_ID\n' +
      'FROM panier AS PA INNER JOIN produit AS P ON PA.PRO_ID = P.PRO_ID\n' +
      'WHERE USE_ID = :id',
      {
        replacements: { id: req.params.userId },
        type: QueryTypes.SELECT
      }
    ).then(panier => {
        res.json(panier);
    }).catch(err => res.status(400).send(err));
}

// Modify the quantity of a basket
exports.update = (req, res) => {
    Paniers.update({
        quantite: req.body.quantite
    }, {
        where: {
            produitId: req.params.produitId
        }
    }).then(panier => {
        res.json(panier);
    }).catch(err => res.status(400).send(err));
}

前端

这就是我的信息的显示方式(仍在开发中,这就是为什么它看起来不像任何东西^^')

为用户显示 2 个篮子,带有 2 个按钮:加号和减号

这就是我迷路的地方......这是我的购物车 pagePage.js :

import React, { useState, useEffect } from 'react';
import { Card, CardHeader, CardMedia, Grid, ButtonGroup, Button} from '@material-ui/core';
import PayPal from '../services/PayPal/paypal'
import {getDetails, updateQuantite, getAllPanier, get} from '../services/API/panier'


export default function PanierPage() {


        // Récupération des détails des paniers
        const [paniers, setPaniers] = useState([])
        const getPaniersDetails = () => [
            getDetails(JSON.parse(localStorage.getItem('User')).id).then(response => {
                setPaniers(response.data)
                console.log(response)
            }).catch(err => console.log(err))
        ]

        const handleIncrement = (id) => {
                updateQuantite(id).then(response => {
                    // ???
            }).catch(err => console.log(err))
        }
        
        const handleDecrement = () => {
        }


        // Affichage des détails des paniers 
        const paniersAffichage = paniers.map((panier) => (
            <Grid container>
                <Card key={panier.PAN_ID}>
                    <CardHeader title={panier.PRO_NOM}/>
                    <CardMedia image={`http://localhost:8090/${panier.PRO_URL}`}/>
                        <Button onClick={() => handleIncrement(panier.PRO_ID)}> + </Button>
                            {panier.PAN_QUANTITE}
                        <Button onClick={handleDecrement}> - </Button>
                </Card>
            </Grid>
        ));


        // Chargement des produits
        useEffect(() => {
            getPaniersDetails();
        }, [])

    return (
            <>
                <Grid>
                    {paniersAffichage}
                </Grid>
                <PayPal/>
            </>
        );
}

解释:

我敢肯定,设置起来非常简单,但在我看来,这对我来说似乎很复杂......

如果我错过了任何重要的点告诉我,我会尽力改变我的帖子

标签: javascriptreactjsaxiossequelize.js

解决方案


您的对象模型没有多大意义。

我会改变它以使其更具活力。

如果您有用户,并且他们有一个购物篮属性,那么这种方法更有意义。

注意:下面的代码是一个粗略的大纲,但应该让您知道如何去做。

interface Database {
    users: User[]; // Array of users.
}

interface User {
    id: number;
    username: string;
    passwordHash: string;
    baskets: Basket[];
}

interface Basket {
    id: number;
    items: Item[]; // array of items;
    date: string;
}

interface Item {
    id: number; // ID of the item.
    name: string;
    imgURL: string;
    description: string[];
    quantity: number;
}

现在,如果我们想要接收数据并将数据发送到数据库,我们会这样做。

interface Basket {
    items: string[]; // list of item id's.
}

// You want to use a session token instead of the user id so noone but the user can access their basket. 
// Normaly baskets will be local to the browser or app and not sored on a servers database. 
// Only past orders should be stored. But in this example, we are storing the current basket too.
async function getBasket(sessionToken: string){
    return await axios.get(`${api.host}/basket`, { 
        headers: {
            Session-Token: sessionToken, // used to identify the user
            Content-Type: "application/json",
        }
    }).data;
}

// we send the basket object, which is just a list of IDs, and the session token.
async function setBasket(basket: Basket, sessionToken: string){
    return await axios.put(`${api.host}/basket`, { 
        headers: {
            Session-Token: sessionToken, // used to identify the user
            Content-Type: "application/json",
        }
    }).data;
}

现在在服务器端,我们可以使用 express 处理请求。

为了使用 express 实现会话,有一个 npm 模块express-session,它是 express 的中间件。当用户登录时,他们将获得一个标头,他们将保存为 cookie 以用于他们未来的请求。当他们注销时,会话将从您的服务器中删除,并且 cookie 在客户端上被删除。

为了增加安全性,您可以设置会话的过期时间。用户将不得不重新登录并获得一个新会话。


// check the documentation to tune it to what you need.
app.use(session({
  secret: 'mySuperSecret',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}))

app.get("/basket", async(req, res) => {
    // here we first check if the session exists.
    if(req.session.views){
        // if it does, then we return the list of baskets.
        const { baskets } = await getUser(req.session.userID);
        res.sendStatus(200).send([success: true, data: baskets]);
    }
    // if not, then we will return a 403 error.
    // we also send a response that matches the layout of the normal response.
    res.sendStatus(403).send([success: false, data: []]);
    
})

app.put("/basket", (req, res) => {
    // here we first check if the session exists.
    if(req.session.views){
        // if it does, then we add the basket to the user.
        addBasket(req.session.userID, basket)
            .then(res.sendStatus(204).send([success: true, data: []]))
    }
    // if not, then we will return a 403 error.
    // we also send a response that matches the layout of the normal response.
    res.sendStatus(403).send([success: false, data: []]);
})

如果您有任何问题,请在评论部分提出。我有空时会回复。


推荐阅读