FETCH JavaScript PHP process the data on the server sent with fetch

I have this doubt of how to process the data brought from my form, I am using javascript with a fetch to receive the data of the form, but I have the doubt of how I should process them in php, nor is the click event of the send button working, the problem is that the server seems not to be receiving the array sent from javascript with the data, agradesco if you give me any source to delve into the topic of fetch api, I am new to javascript and php

my Javascript

registrar.addEventListener("click", () => {
    fetch("../add.php", {
        method: "post",
        body: new FormData(frm) //frm es el id del formulario
    }).then(response => response.text()).then
        (response => {
            // console.log(response);
            // si la respuesta sel servidor es "ok" arroja una alerta personalizada
            if (response == "ok") {
                Swal.fire({
                    icon: 'success',
                    title: 'Registrado',
                    showConfirmButton: false,
                    timer: 1500
                })
                frm.reset();
            }
        }
        )
})
  <form action="" method="post" id="frm">
                      <div class="form-group">              
                       <br>      

                    <div class="form-group">
                        <div class="form-group">
                          <input type="text" name="name_usu" id="name_usu" class="form-control form-control-md" placeholder="Nombre completo" required >
                        </div>
                        <input type="text" name="phone_usu" id="phone_usu" class="form-control form-control-md" placeholder="Numero de teléfono" required>
                      </div>

                        <input type="email" name="nom_usu" id="nom_usu" class="form-control form-control-md" placeholder="Email" required></div>
                        <input type="text" name='torreApto' id="Torre_apto" class="form-control form-control-md" placeholder="Torre y apartamento" required>
                      <label for="FormControlSelect1" class="text-light">Escoja tipo de residente</label>
                      <select class="form-control" name="sel_apto" id="sel_apto" required>
                        <option selected>Propietario</option>
                        <option selected>Arrendado</option>
                        <option selected>Otro</option>
                      </select>
                          
                          <div class="form-group">
                            <label for="Textarea1" class="text-light">Mensaje a enviar</label>
                            <textarea class="form-control" name="mensaje" id="Textarea1" rows="3"></textarea>
                          </div>
                          <br>  
                        <input type="button" class="btn btn-outline-light btn-block border-light text-light font-weight-bold" value="registrar" id="registrar">
                  </form>

addRegister.php

enter if (isset($_POST)) {
$nombre = $_POST['name_usu'];
$telefono = $_POST['phone_usu'];
$email = $_POST['nom_usu'];
$torreApto = $_POST['torreApto'];
$arrendado = $_POST['sel_apto'];
$mensaje = $_POST['mensaje'];
require("connect.php");

// script guardando en la base de datos 
$query = $con->prepare("INSERT INTO informacion(nombre,telefono,email,torreApto,arrendado,mensaje) VALUES (:nom, :tel, :ema, :torr, :arr, :men)");
$query->bindParam(":nom", $nombre);
$query->bindParam(":tel", $telefono);
$query->bindParam(":ema", $email);
$query->bindParam(":torr", $torreApto);
$query->bindParam(":arr", $arrendado);
$query->bindParam(":men", $mensaje);

//ejecuta el script 
$query->execute();
$con = null;
echo "ok";

}

React/Nextjs | Cannot figure out how to properly loop image back to start/end when pressing previous and next arrows

I am using heroicons, tailwindCSS, nextjs/react.

I have tried creating a useState for the index and using useEffect to update it every time. selectedIMG has a state but that didnt work as well. I cannot seem to understand why it is not looping the array when clicking on the arrow icons.

  const [selectedIMG, setSelectedIMG] = useState();


        {/* Popup Image */}
        {selectedIMG && (
          <div className="fixed top-0 z-50 w-[100vw] h-[100vh] flex justify-center items-center backdrop-blur-sm select-none">
            <div className="absolute w-[100vw] h-[100vh] bg-custom-black bg-opacity-60 " />
            <XIcon
              className="w-12 h-12 absolute top-10 right-10 cursor-pointer z-10 p-2 border rounded-full xl:scale-150 bg-opacity-10 bg-white"
              onClick={() => setSelectedIMG()}
            />
            <ArrowLeftIcon
              className="absolute text-white z-50 w-12 h-12 p-2 border rounded-full left-5 lg:left-[10vw] xl:scale-150 cursor-pointer shadow-2xl bg-white bg-opacity-10"
              onClick={() => {
                const selectedIndex = galleryImages.findIndex(
                  (item) => item == selectedIMG
                );

                console.log(selectedIndex);

                if (selectedIndex <= 0) {
                  setSelectedIMG(galleryImages[galleryImages.length]);
                } else {
                  setSelectedIMG(galleryImages[selectedIndex - 1]);
                }
              }}
            />
            <ArrowRightIcon
              className="absolute text-white z-50 w-12 h-12 p-2 border rounded-full right-5 lg:right-[10vw] xl:scale-150 cursor-pointer shadow-2xl bg-white bg-opacity-10"
              onClick={() => {
                const selectedIndex = galleryImages.findIndex(
                  (item) => item.src == selectedIMG.src
                );

                if (selectedIndex == galleryImages.length) {
                  setSelectedIMG(galleryImages[0]);
                } else {
                  setSelectedIMG(galleryImages[selectedIndex + 1]);
                }
              }}
            />
            <div className="relative w-full h-3/4">
              <Image
                priority
                layout="fill"
                objectFit="contain"
                src={selectedIMG.src}
                alt=""
              />
            </div>
          </div>
        )}
        {/*  */}
        <section>
          <PageHeader title={"Gallery"} info={"Showcase of work"} />

          <div className="grid grid-cols-2 sm:grid-cols-3  gap-y-1 gap-x-1 justify-center items-center mt-5">
            {galleryImages.map((img) => (
              <div
                className="relative rounded-sm min-w-[100px] w-full h-full overflow-hidden mx-auto p-3 cursor-pointer"
                key={img.src}
                whileHover={{
                  scale: 1.1,
                  transition: {
                    ease: [0.6, 0.01, -0.05, 0.95],
                  },
                }}
                onClick={() => setSelectedIMG(img)}
              >
                <div>
                  <Image
                    width={"100%"}
                    height={"100%"}
                    layout="responsive"
                    objectFit="cover"
                    src={img.src}
                    alt={img.caption}
                  />
                </div>
              </div>
            ))}
          </div>
        </section>

React RTK, slow UI updates

I’m having issues where the state of my app updates very slowly. Here’s an image of my main page.

enter image description here

Now when you click on a blue item in the map, it’s associated item should be highlighted red in the list below the map.

This works, but it takes like 1-3 seconds to update. It’s slow.

The store is in the root App component:

function App() {
  return (
    <div className="App">
      <Provider store={store}>
        <Header></Header>
        <Main />
      </Provider>
    </div>
  );
}

The map and the list of items are in their own component in <Main />:

  <Map></Map>
  <MainSub></MainSub>

<Map/> dispatches an event to the store on a click event called setActive.

  function handleMarkerClick(data) {
    console.log("click :" + data.name);
    dispatch(setActive({ res: data._id.toString() }));
  }

<MainSub/> contains the list and updates according to state change.

  const restaurantList = useSelector((state) => {
    console.log(state.restaurantSlice);
    return state.restaurantSlice;
  }, shallowEqual);

This is my slice:

import { createAsyncThunk, createSlice, current } from "@reduxjs/toolkit";
const axios = require("axios");
export const fetchRestaurants = createAsyncThunk(
  "fetchRestaurants",
  async (teamId) => {
    console.log(teamId);
    var data = await axios.get("http://localhost:3000/getRestaurant", {
      params: {
        lon: -72.631119,
        lat: 42.206242,
        radius: 1,
      },
    });

    return data.data;
  }
);
export const restaurantSlice = createSlice({
  name: "restaurant",
  initialState: {
    data: { count: 0, data: [] },
    currentActive: 0,
    loading: "",
  },
  reducers: {
    setActive: (state, action) => {
      var getID = action.payload.res;

      state.data.data.map((obj) => {
        if (obj._id === getID) {
          obj.isActive = true;
        }
      });
      state.data.data.map((obj) => {
        if (obj._id === state.currentActive) {
          obj.isActive = false;
        }
      });

      state.currentActive = action.payload.res;
    },
    setRestaurant: (state, action) => {},
    getRestaurant: (state, action) => {},
  },
  extraReducers: (builder) => {
    builder.addCase(fetchRestaurants.fulfilled, (state, action) => {
      console.log(current(state));
      action.payload.data.forEach((x) => {
        x.isActive = false;
      });
      state.data = action.payload;
      state.data.data[0].isActive = true;
      state.currentActive = state.data.data[0]._id;
      state.loading = "loaded";
    });
  },
});

Also, the extraReducer is what gets the list.

(I don’t know if that’s the root issue)

I understand that createSlice uses immer behind the scenes so the mutations to the list in setActive shouldn’t be a problem I think. Also if you look in the chrome dev tools, you’ll see that the console.log in useSelector logs twice. I’m not sure why that’s happening since setActive is only dispatched once.

Here’s a link to the code in github. There’s not a lot of code. Only a few components that are self explanatory. https://github.com/CTMatt23/overflow

Thank you for any input. Again this is React Redux Toolkit.

How JavaScript uses variables when reading json

Like the title, I tried to use variables when reading json, but it didn’t work (

fetch('https://lolimstatic.ml/counts/apis.json').then(
(response) => {
    response.json().then((data) => {
        const apiListFrame = document.querySelector('#als');
        const api = document.createElement('a');
        api.classList.add('btns');
        api.classList.add('button');
        api.classList.add('apilist');
        var rns = Math.round(Math.random()*10);
        colors = ["blue","red","white","orange","pink","green","yellow","skyblue","purple","gray"];
        api.style.background = colors[rns];
        api.style.width = '200px';
        var lstd = Math.round(Math.random()*data[0].counts);
        api.href = 'https://docs.lolimapis.ml/API/'+ data[0].list[lstd] +'/';
        lnm = data[0].list[lstd];
        var xhr = new XMLHttpRequest;
        xhr.open("GET", 'https://lolimstatic.ml/counts/apis/zh.json');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState = 4) {
                const res = xhr.responseText;
                // Here is variables Json
                api.innerText = res.lnm;
                apiListFrame.appendChild(api);
            }
        }
    })
}
)

I think it variables to this:

{
    "lnm": ""
}

But I want variables to this(Suppose the lnm variable is BingImage):

{
    "BingImage": "每日Bing图获取"
}

Can i reload div automaticly without click events?

i want to togle between 2 carts icon,one display when the cart is empty the second when is not,

<div id="div-icon-cart">
        <span class="tools-icon">



        <?php if ( ! WC()->cart->is_empty() ) { ?>
                                

    <img  decoding="async" src="https://txxxx.com/uploads/cart.svg" class="custom-icon" alt="" height="20.738" width="17.626">      
                <?php } else{ ?>


<!-- begin snippet: js hide: false console: true babel: false -->

but the problem is that the cart icon doesn’t change immediately,i need to refrech the page to upload cart icon.
for that i tried to reload div which contains my cart icon

    $document.ready(function(){
        $('#div-icon-cart').load();
        setInterval{fonction(){
            $('#div-icon-cart').load();
        },3000};
    });

but doesn’t work and i don’t know why.i would be grateful for any help

NB:

  • i cant trriger an event like onClick.
  • the right solution for me is to reload div automaticly

Error when uploading image to firebase using react js

I am having issues uploading my picture to firebase, the problem seems to stem from [ firebase storage ] i’ve tried multiple iterations of it and still no luck.

in the console, i saw this error:

FirebaseError: Firebase: No Firebase App ‘[DEFAULT]’ has been created – call Firebase App.initializeApp() (app/no-app).

   import React, { useState, useEffect } from "react";
import { Paper } from "@mui/material";
//import axios from "axios";
import authHeader from "../../features/authentication/AuthHeader";
//import {storage} from "./firebase.js";
import {getStorage,ref,uploadBytes} from 'firebase/storage';

function UserProfile() {
  const [user, setUser] = useState({});

  async function fetchUser() {
    const response = await fetch("http://localhost:9005/getProfile", {
      headers: authHeader(),
    });
    const fetchedUser = await response.json();
    console.log(fetchedUser);
    setUser(fetchedUser);
  }

  useEffect(() => {
    fetchUser();
  }, []);

  //firebase upload
  const allInputs = { imgUrl: "" };
  const [imageAsFile, setImageAsFile] = useState("");
  const [imageAsUrl, SetImageAsUrl] = useState(allInputs);

  const handleImageAsFile = (e) => {
    const image = e.target.files[0];
    setImageAsFile((imageFile) => image);
  };

  const handleFireBaseUpload = e =>{
    e.preventDefault();
    console.log('uploading pic');
    if(imageAsFile===''){
      alert(`image format not supported${typeof(imageAsFile)}`);
    }

    const storage = getStorage();
    const storageRef = ref(storage,'tet');

    uploadBytes(storageRef,imageAsFile).then((snapshot)=>{
      alert('uploading');
    });
    //const uploadTask = storage.ref(`/images/${imageAsFile.name}`).put(imageAsFile);
  }
 

  return (
    <>
      

      <Paper
      
        elevation={6}
        style={{ margin: "10px", padding: "15px", textAlign: "left" }}
        key={user.user_id}
      >
      <div className="pfp">
          <form onSubmit={handleFireBaseUpload}>
            <input type="file" onChange={handleImageAsFile} />
            <p>hgk</p>
            <button>test</button>
          </form>
        </div>
        First Name: {user.firstName}
        <br />
        Last Name: {user.lastName}
        <br />
        Email: {user.email}
        <br />
        Phone: {user.phone}
      </Paper>
    </>
  );
}
export { UserProfile as default };

this is the firebase js

import {initializeApp} from "firebase/app";
import firebase from "firebase/compat/app"
import "firebase/storage" ;




const firebaseConfig = {
    apiKey: "AIzaSyB8vxklg6-m-G8vUYANQ45uzD4OTIa4gsQ",
    authDomain: "dart-cart-273ad.firebaseapp.com",
    projectId: "dart-cart-273ad",
    storageBucket: "dart-cart-273ad.appspot.com",
    messagingSenderId: "41403665604",
    appId: "1:41403665604:web:3cfb4b0c15e705451fcd91"
  };
  //initilize firebase
  firebase.initializeApp(firebaseConfig);

  const storage = firebase.storage();

  export{
    storage, firebase as default
  }

How to style Shopify 2.0 inbox/chat icon (inside an iframe)?

PROBLEM

Shopify’s chat icon gets in the way of a lot of content (a common question on their forums) but the old CSS solutions don’t work because the new inbox/chat icon is now inside an iframe – and my JS is lame.


HAVE TRIED

Have read many Stackoverflow answers as well as blog posts but can’t get it working sorry. And combined with the age of some of the answers, it’s unclear if the answers I’ve tried are the ‘correct’ way of doing things.

Never the less, here’s a simplified version of where I’m at…

<iframe id="dummy-chat-button-iframe" name="dummy-chat-button-iframe" src="about:blank"></iframe>

<script>
  var iframe = document.getElementById("dummy-chat-button-iframe");
  var element = iframe.contentWindow.document.getElementById("dummy-chat-button")[0];
  element.style.height = "40px";
  element.style.width = "40px";
</script>

The above was a test to see if I could affect elements within the iframe, the actual selectors/styles I need to target would be…

button#dummy-chat-button.chat-toggle {
  margin-top: 3px;
  height: 40px;
  width: 40px;
  padding: 0;
}
button.chat-toggle svg {
  width: auto;
  height: 25px;
  margin: auto;
}

NOTE: I have no control over the iframe’s HTML, styles or the iframe call itself, so can only use CSS and JS from outside the iframe (if possible).


QUESTIONS

  1. Based on the above info, can anyone show me the JS required to style elements within the iframe?
  2. Given the amount of styles I need to change, should I add a <style> element to the head of the iframe and is this possible using JS?

Sorry my JS is so limited, any help or pointers in the right direction would be much appreciated.

Cheers, Ben

Most performant and simplest way to concatenate object keys within two levels of arrays with Javascript? [closed]

I have the following array structure:

const array = [
  {
    id: 1,
    name: "Module 1",
    form:[
      {field:"name"},
      {field:"email"}
    ]
  },
  {
    id: 2,
    name: "Module 2",
    form:[
      {field:"name"},
      {field:"address"}
    ]
  },
  {
    id: 3,
    name: "Module 3",
    form:[
      {field:"email"},
      {field:"age"}
    ]
  }
] 

My challenge here is to generate a new array with all form fields so that they are not repeated. What would be the most performative and simplified way to do this with Javascript?

In the example above I need to output the following array:

const arrayResult = ["name","email","address","age"]

Mapping causing all array elements to appear in React

Im trying to make a component in React more dynamic by having the headings by stored in an array and mapped each time with the html element. However with each map of the element it outputs all of the values in the headings array. I would like it so the first iteration has the first heading value then the second has the second heading and so on.
Any for anyone who doesn’t recognise it the messy CSS is Tailwind.

Heres the component:

import * as React from 'react';

//Maps element based on the number of itterations
const itterations = [1, 2, 3, 4, 5, 6];
const headings = ['text', 'text2', 'text3', 'text4', 'text5', 'text6'];
const items = itterations.map((itterations) =>
    <div class="flex flex-row lg:flex-col mx-5 lg:mx-2 lg:mt-0 my-5 pb-5 items-center md:items-start lg:bg-white border-b-2 border-red-300">
        <a href="#" class="w-[26%] lg:w-full mr-5 lg:mr-0 rounded-sm"><img src="./images/elden-ring-thumbnail.jpg" alt="Lorem Impsum"></img></a>
        <div class="md:flex md:flex-col lg:px-3">
            <h6 class="font-bold lg:my-3">{headings}</h6>
            <p class="hidden md:block my-2 lg:my-0">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sodales.</p>
        </div>
    </div>
);

export default function RecentReviews() {
    return (
        <div class="mx-1 lg:w-[60%] lg:m-auto">
            <h3 class="bg-red-500 font-bold text-white my-5 lg:my-0 px-4 py-0.5">Recent Reviews</h3>

            <div class="lg:grid grid-cols-3 grid-row-2">
                <>{items}</>
            </div>
        </div>
    );
};

This is what it currently looks like:
enter image description here

This is how I want it too look:
enter image description here

Trying to get webpack site with custom index.html to work on github pages

I’ve been using the HTMLWebpackPlugin to generate custom index.html to give me the benefit of having the index.html file in the ‘src’ folder rather than the ‘dist’ folder, and also to create multiple HTML files. However, I realized that that this prevents my Webpack sites from being hosted on Github pages. I wonder if there is a way to get around this.

The webpack.config.js file is displayed here:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    devServer: {
        static: './dist',
        historyApiFallback: true,
        open: true,
        compress: true,
        hot: true,
        port: 8080,
    },
    devtool: 'inline-source-map',
    entry: {
        index: {
            import: './src/index.js',
            dependOn: 'shared',
        },
        shared: 'lodash',
    },
    mode: "development",
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
        clean: true,
    },
        optimization: {
        runtimeChunk: 'single',
        splitChunks: {
            chunks: 'all',
        },
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Custom Template',
            template: './src/index.html',
            minify: true,
        }),
    ],
    module: {
        rules: [
            {
                test: /.html$/i,
                loader: "html-loader",
            },
            {
                test: /.txt$/,
                use: 'raw-loader'
            },
            {
                test: /.css$/i,
                use: ['style-loader', 'css-loader'],
            },
            {
                test: /.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource',
            },
            {
                test: /.(woff|woff2|eot|ttf|otf)$/i,
                type: 'asset/resource',
            },
            {
                test: /.(csv|tsv)$/i,
                use: ['csv-loader'],
            },
            {
                test: /.xml$/i,
                use: ['xml-loader'],
            },
            {
                test: /.js$/,
                loader: 'babel-loader',
            },
        ],
    },
};

MERN – 500 Server Error when trying to create an order for ecommerce section

I’m working on a podcast app that has an e-commerce section for which I am following this tutorial: https://www.youtube.com/watch?v=CDtPMR5y0QU

I’ve been getting the following error from the network tab when I click the Place Order button:

message: "Order validation failed: orderItems.0.product: Cast to ObjectId failed for value "1" (type string) at path "product", orderItems.0._id: Cast to ObjectId failed for value "1" (type string) at path "_id", orderItems.0.image: Path `image` is required., orderItems.1.image: Path `image` is required."

In the console, there is this error:
POST http://localhost:3000/api/orders 500 (Internal Server Error)

I think this has to do with the images not showing up from the backend…it just has the icon for when a photo does not show up. Could it be related to the folder structure? I’ve followed the code in the video exactly. This error came after implementing Video 28.

Screenshot of the folder structure:
folder-structure

I added two “images” folders because they weren’t showing up and I wanted to test them in the src and public folders. It didn’t work for either.

Here is my code:

BACKEND

This is the data that is fed into the MongoDB models

  users: [
    {
      name: "example",
      email: "[email protected]",
      password: bcrypt.hashSync("123456"),
      isAdmin: true,
    },
    {
      name: "example",
      email: "[email protected]",
      password: bcrypt.hashSync("123456"),
      isAdmin: false,
    },
  ],
  products: [
    {
      name: "LTBT Sweater",
      slug: "ltbt-sweater",
      price: 70,
      image: "/images/1.png",
      category: "Hoodies",
      countInStock: 10,
      description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
    },
    {
      name: "LTBT Keychain",
      slug: "ltbt-keychain",
      price: 50,
      image: "/images/1.png",
      category: "Accessories",
      countInStock: 9,
      description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
    },
    {
      name: "LTBT Sticker",
      slug: "ltbt-sticker",
      price: 20,
      image: "/images/1.png",
      category: "Stickers",
      countInStock: 17,
      description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
    },
  ],
};

export default productData;

This is the db model:

import mongoose from "mongoose";

const orderSchema = new mongoose.Schema(
  {
    orderItems: [
      {
        slug: { type: String, required: true },
        name: { type: String, required: true },
        quantity: { type: Number, required: true },
        image: { type: String, required: true },
        price: { type: Number, required: true },
        product: {
          type: mongoose.Schema.Types.ObjectId,
          ref: "Product",
          required: true,
        },
      },
    ],
    shippingAddress: {
      fullName: { type: String, required: true },
      address: { type: String, required: true },
      city: { type: String, required: true },
      postalCode: { type: String, required: true },
      country: { type: String, required: true },
    },
    paymentMethod: { type: String, required: true },
    paymentResult: {
      id: String,
      status: String,
      update_time: String,
      email_address: String,
    },
    itemsPrice: { type: Number, required: true },
    shippingPrice: { type: Number, required: true },
    taxPrice: { type: Number, required: true },
    totalPrice: { type: Number, required: true },
    user: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
    isPaid: { type: Boolean, default: false },
    paidAt: { type: Date },
    isDelivered: { type: Boolean, default: false },
    deliveredAt: { type: Date },
  },
  {
    timestamps: true,
  }
);

const Order = mongoose.model("Order", orderSchema);
export default Order;

This is the orderRoutes file

import express from "express";
import Order from "../models/orderModel.js";
import expressAsyncHandler from "express-async-handler";
import { isAuth } from "../utils.js";

const orderRouter = express.Router();
orderRouter.post(
  "/",
  isAuth,
  expressAsyncHandler(async (req, res) => {
    const newOrder = new Order({
      orderItems: req.body.orderItems.map((x) => ({ ...x, product: x._id })),
      shippingAddress: req.body.shippingAddress,
      paymentMethod: req.body.paymentMethod,
      itemsPrice: req.body.itemsPrice,
      shippingPrice: req.body.shippingPrice,
      taxPrice: req.body.taxPrice,
      totalPrice: req.body.totalPrice,
      user: req.user._id,
    });

    const order = await newOrder.save();
    res.status(201).send({ message: "New Order Created", order });
  })
);
export default orderRouter;

This is the server.js file

import cors from "cors";
import mongoose from "mongoose";
import dotenv from "dotenv";
import seedRouter from "./routes/seedRoutes.js";
import productRouter from "./routes/productRoutes.js";
import userRouter from "./routes/userRoutes.js";
import orderRouter from "./routes/orderRoutes.js";

dotenv.config();

mongoose
  .connect(process.env.MONGODB_URI)
  .then(() => {
    console.log("Connected to DB");
  })
  .catch((err) => {
    console.log(err.message);
  });

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());

app.use("/api/seed", seedRouter);
app.use("/api/orders", orderRouter);
app.use("/api/store", productRouter);
app.use("/api/users", userRouter);

app.use((err, req, res, next) => {
  res.status(500).send({ message: err.message });
});

const port = process.env.PORT || 5000;
app.listen(port, () => {
  console.log(`SERVER RUNNING ON PORT ${port}`);
});

FRONTEND

Here is the page that has the button (Place Order button)

import CheckoutSteps from "../components/CheckoutSteps";
import { Helmet } from "react-helmet-async";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import ListGroup from "react-bootstrap/ListGroup";
import { Link, useNavigate } from "react-router-dom";
import { useContext, useEffect, useReducer } from "react";
import { Store } from "../Store";
import { toast } from "react-toastify";
import { getError } from "../utils";
import axios from "axios";
import LoadingBox from "../components/LoadingBox";

//reducer for creating an order
const reducer = (state, action) => {
  switch (action.type) {
    case "CREATE_REQUEST":
      return { ...state, loading: true };
    case "CREATE_SUCCESS":
      return { ...state, loading: false };
    case "CREATE_FAIL":
      return { ...state, loading: false };
    default:
      return state;
  }
};

export default function PlaceOrder() {
  const navigate = useNavigate();

  const { state, dispatch: ctxDispatch } = useContext(Store);
  const { cart, userInfo } = state;

  const [{ loading }, dispatch] = useReducer(reducer, {
    loading: false,
  });

  //round to 2 decimal places
  const round = (num) => Math.round(num * 100 + Number.EPSILON) / 100;

  //calculate items price
  cart.itemsPrice = round(
    cart.cartItems.reduce((a, c) => a + c.quantity * c.price, 0)
  );

  //if total price is more than 100, make shipping price 15 otherwise it is 10
  cart.shippingPrice = cart.itemsPrice > 100 ? round(10) : round(15);

  //tax is 13%
  cart.taxPrice = round(0.13 * cart.itemsPrice);

  //total price
  cart.totalPrice = cart.itemsPrice + cart.shippingPrice + cart.taxPrice;

  const placeOrderHandler = async () => {
    try {
      dispatch({ type: "CREATE_REQUEST" });

      const { data } = await axios.post(
        "/api/orders",
        {
          orderItems: cart.cartItems,
          shippingAddress: cart.shippingAddress,
          paymentMethod: cart.paymentMethod,
          itemsPrice: cart.itemsPrice,
          shippingPrice: cart.shippingPrice,
          taxPrice: cart.taxPrice,
          totalPrice: cart.totalPrice,
        },
        {
          headers: {
            authorization: `Bearer ${userInfo.token}`,
          },
        }
      );
      ctxDispatch({ type: "CART_CLEAR" });
      dispatch({ type: "CREATE_SUCCESS" });
      localStorage.removeItem("cartItems");
      navigate(`/order/${data.order._id}`);
    } catch (err) {
      dispatch({ type: "CREATE_FAIL" });
      toast.error(getError(err));
    }
  };

  useEffect(() => {
    if (!cart.paymentMethod) {
      navigate("/payment");
    }
  }, [cart, navigate]);

  return (
    <div>
      <CheckoutSteps step1 step2 step3 step4></CheckoutSteps>
      <Helmet>
        <title>LTBT | Preview Order</title>
      </Helmet>
      <h1 className="my-3">Preview Order</h1>
      <Row>
        <Col md={8}>
          <Card className="mb-3">
            <Card.Body>
              <Card.Title>Shipping</Card.Title>
              <Card.Text>
                <strong>Name:</strong> {cart.shippingAddress.fullName} <br />
                <strong>Address: </strong> {cart.shippingAddress.address},
                {cart.shippingAddress.city}, {cart.shippingAddress.postalCode},
                {cart.shippingAddress.country}
              </Card.Text>
              <Link to="/shipping">Edit</Link>
            </Card.Body>
          </Card>

          <Card className="mb-3">
            <Card.Body>
              <Card.Title>Payment</Card.Title>
              <Card.Text>
                <strong>Method:</strong> {cart.paymentMethod}
              </Card.Text>
              <Link to="/payment">Edit</Link>
            </Card.Body>
          </Card>

          <Card className="mb-3">
            <Card.Body>
              <Card.Title>Items</Card.Title>
              <ListGroup variant="flush">
                {cart.cartItems.map((item) => (
                  <ListGroup.Item key={item._id}>
                    <Row className="align-items-center">
                      <Col md={6}>
                        <img
                          src={item.image}
                          alt={item.name}
                          className="img-fluid rounded img-thumbnail"
                        ></img>{" "}
                        <Link to={`/store/${item.slug}`}>{item.name}</Link>
                      </Col>
                      <Col md={3}>
                        <span>{item.quantity}</span>
                      </Col>
                      <Col md={3}>$ {item.price}</Col>
                    </Row>
                  </ListGroup.Item>
                ))}
              </ListGroup>
              <Link to="/cart">Edit</Link>
            </Card.Body>
          </Card>
        </Col>
        <Col md={4}>
          <Card>
            <Card.Body>
              <Card.Title>Order Summary</Card.Title>
              <ListGroup variant="flush">
                <ListGroup.Item>
                  <Row>
                    <Col>Items</Col>
                    <Col>$ {cart.itemsPrice.toFixed(2)}</Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <Row>
                    <Col>Shipping</Col>
                    <Col>$ {cart.shippingPrice.toFixed(2)}</Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <Row>
                    <Col>Tax</Col>
                    <Col>$ {cart.taxPrice.toFixed(2)}</Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <Row>
                    <Col>
                      <strong> Order Total</strong>
                    </Col>
                    <Col>
                      <strong>$ {cart.totalPrice.toFixed(2)}</strong>
                    </Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <div className="d-grid">
                    <Button
                      type="button"
                      onClick={placeOrderHandler}
                      disabled={cart.cartItems.length === 0}
                    >
                      Place Order
                    </Button>
                  </div>
                  {loading && <LoadingBox></LoadingBox>}
                </ListGroup.Item>
              </ListGroup>
            </Card.Body>
          </Card>
        </Col>
      </Row>
    </div>
  );
}

Store.js file


export const Store = createContext();

//define initial state in cart based on local storage
const initialState = {
  //check if user exists
  userInfo: localStorage.getItem("userInfo")
    ? JSON.parse(localStorage.getItem("userInfo"))
    : null,

  cart: {
    //get shipping address, payment method and cart items based on user
    shippingAddress: localStorage.getItem("shippingAddress")
      ? JSON.parse(localStorage.getItem("shippingAddress"))
      : {},
    paymentMethod: localStorage.getItem("paymentMethod")
      ? localStorage.getItem("paymentMethod")
      : "",
    cartItems: localStorage.getItem("cartItems")
      ? JSON.parse(localStorage.getItem("cartItems"))
      : [],
  },
};

//update state in cart
//instead of creating duplicate items of the same product, we increase the amount of the one product if button is pressed more than once

function reducer(state, action) {
  switch (action.type) {
    //add items to cart
    case "CART_ADD_ITEM":
      const newItem = action.payload;
      const existItem = state.cart.cartItems.find(
        (item) => item._id === newItem._id
      );
      const cartItems = existItem
        ? state.cart.cartItems.map((item) =>
            item._id === existItem._id ? newItem : item
          )
        : [...state.cart.cartItems, newItem];
      localStorage.setItem("cartItems", JSON.stringify(cartItems));
      return { ...state, cart: { ...state.cart, cartItems } };
    //second case: remove item from cart
    case "CART_REMOVE_ITEM": {
      const cartItems = state.cart.cartItems.filter(
        (item) => item._id !== action.payload._id
      );
      localStorage.setItem("cartItems", JSON.stringify(cartItems));
      return { ...state, cart: { ...state.cart, cartItems } };
    }
    //clear cart
    case "CART_CLEAR":
      return { ...state, cart: { ...state.cart, cartItems: [] } };
    //update user info based on data from the backend
    case "USER_SIGNIN":
      return { ...state, userInfo: action.payload };
    //case where user is signed out
    case "USER_SIGNOUT":
      return {
        ...state,
        userInfo: null,
        cart: {
          cartItems: [],
          shippingAddress: {},
          paymentMethod: "",
        },
      };
    //update shipping address with data from payload
    case "SAVE_SHIPPING_ADDRESS":
      return {
        ...state,
        cart: { ...state.cart, shippingAddress: action.payload },
      };
    //save payment method
    case "SAVE_PAYMENT_METHOD":
      return {
        ...state,
        cart: { ...state.cart, paymentMethod: action.payload },
      };
    default:
      return state;
  }
}

export function StoreProvider(props) {
  const [state, dispatch] = useReducer(reducer, initialState);
  const value = { state, dispatch: dispatch };
  return <Store.Provider value={value}>{props.children}</Store.Provider>;
}

Please provide any insights you have. I’m really not sure why the button gives this error. Thank you!!

Is there any way that I can add another value to a key in an object within React?

I will have a list of objects that are going to be entered by an input field. I have it working where it will create the list of objects, but when I try to add another value to one of the objects that already exist. It will just replace the previous value within it.

Current output when I console.log()

const [ tags, setTags ] = useState({
1: 'hello',
2: 'world',
3: 'goodbye'
})

My expected output if person 1 adds the tag ‘testing’.

const [ tags, setTags ] = useState({
1: ['hello', 'testing'],
2: 'world',
3: 'goodbye'
})

The function that I have so far that is taking the value from the input. A is an id number and B is the new tag.

function updateTags(a, b){

  if(tags.hasOwnProperty(a)){
    setTags((prevTags) => {
      return {
        ...prevTags,
        [a]: ????
      }
    })
  }else{
    setTags((prevTags) => {
      return {
        ...prevTags,
        [a]: b
      }
    })
  }

If you need more information please let me know.

PHP (Stripe) – Uncaught (in promise) SyntaxError: Unexpected token { in JSON at position 220

I’m trying to calculate the order amount in the function but it keeps throwing the error

Uncaught (in promise) SyntaxError: Unexpected token { in JSON at
position 220

& this is the response in the network tab

[
    {
        "name": "Peanut Butter & Oats",
        "price": 7.99,
        "quantity": 6,
        "size": "N/A"
    },
    {
        "name": "Oatmeal & Blueberry",
        "price": 9.99,
        "quantity": 3,
        "size": "N/A"
    },
    {
        "name": "Chicken Liver & Gizzards",
        "price": 4.99,
        "quantity": 1,
        "size": "N/A"
    }
]{
    "clientSecret": "SECRET_KEY"
}

JavaScript:

async function initialize() {
  const clientSecret = await fetch("create.php", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({items}),
  }).then((r) => r.json());

  
  elements = stripe.elements({ clientSecret });

  const paymentElement = elements.create("payment", {
      fields: {
        billingDetails: {
            name: "auto",
            email: "auto",
        }
      }
  });
  paymentElement.mount("#payment-element");
}

PHP:

function calculateOrderAmount(array $items): int {
    // Replace this constant with a calculation of the order's amount
    // Calculate the order total on the server to prevent
    // people from directly manipulating the amount on the client

    
    echo json_encode($items);
    
    /**$total = 0;
    for ($i = 0; $i < count($items); $i++) {
        $total += ($items[i].quantity) * $items[$i].price;
        //$total += 100;
    }**/
    return 1400;
}

header('Content-Type: application/json');

try {
    // retrieve JSON from POST body
    $jsonStr = file_get_contents('php://input');
    $jsonObj = json_decode($jsonStr);
    
    // Create a PaymentIntent with amount and currency
    $paymentIntent = StripePaymentIntent::create([
        'amount' => calculateOrderAmount($jsonObj->items),
        'currency' => 'USD',
        'automatic_payment_methods' => [
            'enabled' => true,
        ],
        'receipt_email' => '[email protected]',
    ]);

    $output = [
        'clientSecret' => $paymentIntent->client_secret,
    ];

    echo json_encode($output);
} catch (Error $e) {
    http_response_code(500);
    echo json_encode(['error' => $e->getMessage()]);
}

If I remove the echo statement the error goes away but the commented out for loop ( inside the calculateOrderAmount function) is basically what I want to do because I need to calculate the price based on that data, but it keeps giving me a json error but I followed the code from the Stripe docs.

How to get values on the third object of a Json with Javascript

I am doing a get request on JS and with the json reponse i want to get some values, for example product and color, but i don’t know how i can go more deeper on the next levels of the objects of the Json.

the Json:

{    
"items": {        
    "1man": {
        "312favorites": {
            "155description": {
                "color": "red",
                "price": 2.76666
            }
          }
        }
    }

}

I just can go until the 1man level i don’t know how to get the next levels, my code until now

console.log(response.data.items['1man']);

If i try for example console.log(response.data.items['1man'].312favorites i get error on VScode, i want go to until the color value…

Does someone can help me here?