Strip html tags in Javascrip/PHP

Is there a way how I can strip the html tags in an textarea body, when I insert the data in mysql I use PHP BBCODE for Youtube videos like [vide=link] and in the edit textarea I use Javascript and outputs html tags instead of PHP BBCODE like

Javascript textarea:

var currentComment = $("#message_" + id + " .message-content").html();
var editText = '<div class="contact-form-area"><form id="post_form2"><div class="row"><div class="col-12"><textarea name="post_content2" id="post_content'+id+'" class="edit_comment">'+currentComment+'</textarea></div><div class="col-12"><input type="hidden" class="id_content" id="'+id+'" /><button type="button" class="cancel btn vizew-btn" style="float:left;" data-message="'+currentComment+'" id="'+id+'"> Cancel</button> <button type="button" class="save btn vizew-btn" id="'+id+'" style="float:right;"> Save</button></div></div></form></div>';

Image of exposed html tags

I tried usign this escape function but didn’t worked out.

function escapeHtml(unsafe)
{
    return unsafe
         .replace(/&/g, "&amp;")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
 }

I want to know if is a way to print the PHP BBCODE in the textarea instead of the hmtl tags.

Update list when adding a new item to the list

I have a PR-issue linker program. In the links screen, where I show a table of PRs, when clicking on a PR, a dialog appears with a list of issues, for that specific PR. In that dialog, I have an Add another issue button to add another issue to the issues list.

The problem is, when a new issue is added, it doesn’t appear on the issues list, until I close the dialog and reopen. What should I do to update the list of issues when I add another issue to the list. Currently, I need to close and reopen the dialog, which is not a good UX.

Due to the poor design in the early stages, I am dealing with 5 JS files. Here are them:


The screen (1st JS file):

function PossibleLinks() {
  const location = useLocation();
  const id = location.state.id;
  const projectId = location.state.projectId;
  const [repos, setRepos] = useState([]);
  const [selectedRepo, setSelectedRepo] = useState(null);
  const [jiraRepoId, setJiraRepoId] = useState(0);
  const [rowCount, setRowCount] = useState(10);

  useEffect(() => {
    getRepos();
  }, []);
  
  useEffect(() => {
    getJiraRepoId();
  }, 0);

  const getRepos = async () => {
    const res = await getRepositories(projectId);
    setRepos(res.filter((item) => item.platform !== "jira"));
    setSelectedRepo(res[0].id);
  };

  const getJiraRepoId = async () => {
    const res = await getRepositories(projectId);

    for (let i = 0; i < res.length; i++) {
      if (res[i].platform === "jira") {
        setJiraRepoId(res[i].id);
        break;
      }
    }
  };

  return (
    <div className="project">
      <Sidebar2 id={id} projectId={projectId}></Sidebar2>
      <div className="projectContainer">
        <h2 className="title" align="left">
          Possible Links
        </h2>
        >
        {selectedRepo !== null && (
          <PossibleLinksData
            projectId={projectId}
            jrId={jiraRepoId}
            rId={selectedRepo}
            rowCount={rowCount}
          >
          </PossibleLinksData>
        )}
      </div>
    </div>
  );
}

export default PossibleLinks;

The data (2nd JS file):

function PossibleLinksData({ jrId, rId, rowCount }) {
  const location = useLocation();
  const projectId = location.state.projectId;
  const [data, setData] = useState(null);
  const [currentPageNo, setCurrentPageNo] = useState(1);
  const [lastPageNo, setLastPageNo] = useState();

  useEffect(() => {
    getPossLinks();
    setCurrentPageNo(1)
  }, [rId, rowCount]);

  const getPossLinks = async () => {
    const res = await getPossibleLinks(projectId, rId, rowCount);
    setLastPageNo(Math.ceil(res.count / rowCount));
    setData(res);
  };

  const getPossLinksByPage = async (pageNo = currentPageNo) => {
    console.log("1 getPossLinksByPage --- ");
    const res = await getPossibleLinksByPage(projectId, rId, pageNo, rowCount);
    setData(res);
  };

  const handleChange = (event, value) => {
    setCurrentPageNo(value);
    getPossLinksByPage(value);
  };
  

  return (
    <div sx={{ minWidth: 700 }}>
      {data !== null ? (
        <PossibleLinksTable
          data={data.results}
          rId={rId}
          jrId={jrId}
          getPossLinksByPage={getPossLinksByPage}
        ></PossibleLinksTable>
      ) : null}
      {data !== null ? (
        <Pagination
          count={lastPageNo}
          page={currentPageNo}
          onChange={handleChange}
        />
      ) : null}
    </div>
  );
}

export default PossibleLinksData;

The Table of PRs (3rd JS file):

function PossibleLinksTable({ data, rId, jrId, getPossLinksByPage }) {
  const location = useLocation();
  const projectId = location.state.projectId;
  const [formattedData, setFormattedData] = useState([]);
  const [filteredData, setFilteredData] = useState([]); // filtered data
  const [openDialog, setOpenDialog] = useState(false);
  const [selected, setSelected] = useState(null);

  useEffect(() => {
    // formatting the data here
    setFormattedData(data);
  }, [data]);

  useEffect(() => {
    if (selected !== null) setOpenDialog(true);
  }, [selected]);

  return (
    <div sx={{ minWidth: 700 }}>
      <Box sx={{ minWidth: 700 }}>
        <TableContainer sx={{ minWidth: 700 }}>
          <Table size="small" sx={{ minWidth: 700 }}>
            <TableHead sx={{ minWidth: 700 }}>
              // some table heads here
            </TableHead>
            {formattedData.length !== 0 ? (
              <TableBody>
                {formattedData.map((item, index) => (
                  <TableRow>
                    // some table cells here
                    <TableCell align="center">
                      <IconButton
                        sx={{ color: "white" }}
                        onClick={() => setSelected(item)}
                      >
                        <AddLinkIcon></AddLinkIcon>
                      </IconButton>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            ) : (
              <TableBody></TableBody>
            )}
          </Table>
        </TableContainer>
        {selected && (
          <PossibleLinksCards
            item={selected}
            open={openDialog}
            close={handleCloseDialog}
            rId={rId}
            jrId={jrId}
            getPossLinksByPage={getPossLinksByPage}
          ></PossibleLinksCards>
        )}
      </Box>
    </div>
  );
}

export default PossibleLinksTable;

The dialog (4th JS file):

function PossibleLinksCards({
  item,
  open,
  close,
  rId,
  jrId,
  getPossLinksByPage,
}) {
  const [selectedIssues, setSelectedIssues] = useState([]);
  const [selectedRanks, setSelectedRanks] = useState([]);
  const location = useLocation();
  const [hasAccess, setHasAccess] = useState(false);
  const [alertOpen, setAlertOpen] = useState(false);
  const [mes, setMes] = useState("");
  const [isFailed, setIsFailed] = useState(false);
  const projectId = location.state.projectId;
  const [selected, setSelected] = useState(null);
  const [openDialog, setOpenDialog] = useState(false);

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

  const getCurrentProject = async () => {
    const res = await getProject(projectId);
    setHasAccess(res.user_role === "PM");
  };

  useEffect(() => {
    // formatting issues
  }, [item]);

  const handleSelected = (index) => {
    // handling the selected issues array
  };

  useEffect(() => {
    console.log(selectedIssues);
    console.log(selectedRanks);
  }, [selectedIssues, selectedRanks]);

  useEffect(() => {
    if (selected !== null) setOpenDialog(true);
  }, [selected]);

  const handleCloseDialog = () => {
    setOpenDialog(false);
    setSelected(null);
  };

  return (
    <Dialog open={open} onClose={close}>
      <DialogContent>
        <DialogContentText>
          <TableContainer>
            <Table sx={{ minWidth: 650 }} size="small">
              <TableHead>
                // some table heads
              </TableHead>
              <TableBody>
                {item.possible_links.map((link, index) => (
                  <TableRow>
                    //some table cells
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
        </DialogContentText>
      </DialogContent>
      <DialogActions
      >
        <Button
          disabled={!hasAccess}
          onClick={() => setSelected(item)}
        >
          Add Another Issue
        </Button>

        {selected && (
          <AddAnotherIssueCard
            item={selected}
            open={openDialog}
            close={handleCloseDialog}
            rId={rId}
            jrId={jrId}
            getPossLinksByPage={getPossLinksByPage}
          ></AddAnotherIssueCard>
        )}
      </DialogActions>
    </Dialog>
  );
}

export default PossibleLinksCards;


The Add Another Issue Dialog (5th JS file):

function AddAnotherIssueCard({
  item,
  open,
  close,
  rId,
  jrId,
  getPossLinksByPage,
}) {
  const location = useLocation();
  const [hasAccess, setHasAccess] = useState(false);
  const projectId = location.state.projectId;
  const [selected, setSelected] = useState(null);
  const [text, setText] = useState("");
  const [openDialog, setOpenDialog] = useState(false);
  const [issues, setIssues] = useState([null]);

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

  const getCurrentProject = async () => {
    const res = await getProject(projectId);
    setHasAccess(res.user_role === "PM");
  };

  useEffect(() => {
    if (selected !== null) setOpenDialog(true);
  }, [selected]);

  const getIssues = async () => {
    const res = await getIssuesById(projectId, jrId, text);
    if (res.length !== 0) {
      setIssues(res);
    } else {
      setIssues([null]);
    }
  };

  const handleRelinkClick = async () => {
    if (issues[0] === null) {
      console.log("Please select an issue");
    } else {
      const body = {
        pull_request: item.id,
        issue: issues[0].id,
      };
      const res = await addAnotherIssue(projectId, rId, body);
      setTimeout(close, 500);
      await getPossLinksByPage();
    }
  };

  return (
    <div>
      <Dialog open={open} onClose={close}>
        <DialogContent>
          // Here I GET the issue object.
        </DialogContent>
        <DialogActions>
          <Button
            disabled={!hasAccess}
            variant="contained"
            color="success"
            onClick={handleRelinkClick}
          >
            ADD
          </Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}

export default AddAnotherIssueCard;

No value exists in scope for the shorthand property. Either declare one or provide an initializer

I am new to TypeScript.

I am getting the error No value exists in scope for the shorthand property ‘firstName’. Either declare one or provide an initializer. when using Prisma with Next.js. I am trying to create a new user in my DB.

User model in schema.prisma

model User {
  id            Int      @id @default(autoincrement())
  email         String   @unique
  firstName     String
  middleName    String?
  lastName      String
  dateOfBirth   DateTime
  mobileNumber  String   @unique
  idType        String
  idNumber      String   @unique
  idExpirtyDate DateTime
  idIssueState  DateTime
  streetAddress String
  suburb        String
  postCode      Int
  state         String
  bsb           Int      @unique
  accountNumber Int      @unique
  payIdType     String
  payId         String   @unique
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}

createUser() function is as below.

export async function createUser(user: FormData) {
  const prisma = new PrismaClient()

  await prisma.user.create({
    data: {
      firstName,
      lastName,
      middleName,
      email,
      dateOfBirth,
      mobileNumber,
      idType,
      idNumber,
      idExpirtyDate,
      idIssueState,
      streetAdddress,
      suburb,
      postCode,
      state,
      bsb,
      accountNumber,
      payIdType,
      payId,
    },
  })
}

Below is the where I am getting the FormData. It is from a component.

  async function handleFormData(userData: FormData) {
    'use server'
    await createUser(userData)
  }

Any help is appreciated.

Comparing stored hashed passwords and user entered passwords

i’m have trouble with comparing stored hashed passwords with user entered password in my login endpoint to give users access, below is my server.js file where my signup and login endpoints are.

const express = require('express');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const mongoose = require('mongoose');
const cors = require('cors');

const secretKey = require('./jwt-token');

const app = express();
app.use(cors());
app.use(express.json());

// MongoDB connection URI
const uri = 'mongodb://localhost:27017/final-year-project';

// Connect to the MongoDB database
mongoose
  .connect(uri, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => {
    console.log('Connected to the database');
    app.listen(3000);
    console.log('app connected on port 3000');
  })
  .catch((error) => {
    console.error('Failed to connect to the database:', error);
  });

// Define the user schema
const userSchema = new mongoose.Schema({
  firstName: { type: String, required: true },
  lastName: { type: String, required: true },
  email: { type: String, required: true, unique: true },
  role: { type: String, required: true },
  password: { type: String, required: true },
}, { collection: 'users' });

// Define the user model
const User = mongoose.model('User', userSchema);

class AuthResponseData {
  constructor(user) {
    this.user = user;
  }
}

// Signup endpoint
app.post('/signup', async (req, res) => {
    try {
      // Extract user data from request body
      const { 
        firstName, 
        lastName, 
        email, 
        role,
        password } = req.body;
  
      // Check if email is already taken
      const existingUser = await User.findOne({ email });
      if (existingUser) {
        return res.status(400).json({ message: 'Email already exists' });
      }
  
      // Set a default password if the provided password is empty
      let plainTextPassword = password;
      if (!plainTextPassword) {
        plainTextPassword = 'defaultPassword123';
      }
  
      // Generate a salt asynchronously
      bcrypt.genSalt(10, (saltError, salt) => {
        if (saltError) {
          console.error('Error generating salt:', saltError);
          return res.status(500).json({ message: 'Internal server error' });
        }
  
        // Hash the password asynchronously
        bcrypt.hash(plainTextPassword, salt, async (hashError, hashedPassword) => {
          if (hashError) {
            console.error('Error hashing password:', hashError);
            return res.status(500).json({ message: 'Internal server error' });
          }
  
          try {
            // Create a new user object
            const newUser = new User({
              firstName,
              lastName,
              email,
              role,
              password: hashedPassword,
            });
  
            // Save the user to the database
            await newUser.save();
  
            // Generate a JSON Web Token (JWT)
            const token = jwt.sign({ email: newUser.email }, secretKey);
  
            // Set token expiration date (e.g., 1 hour from now)
            const expirationDate = new Date().getTime() + 3600000;
  
            // Create a new user instance
            const user = {
              firstName: newUser.firstName,
              lastName: newUser.lastName,
              email: newUser.email,
              role: newUser.role,
              id: newUser._id,
              _token: token,
              _tokenExpirationDate: expirationDate,
            };
  
            // Return the authentication response with user details
            const authResponse = new AuthResponseData(user);
  
            res.status(201).json(authResponse);
          } catch (error) {
            console.error(error);
            res.status(500).json({ message: 'Internal server error' });
          }
        });
      });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Internal server error' });
    }
    console.log(req.body)
  });
  
// Login endpoint
app.post('/login', async (req, res) => {
  try {
    // Extract user data from request body
    const { email, password } = req.body;
    const userEmail = req.body.email;
    const userPassword = req.body.password;

    console.log(userEmail);
    console.log(userPassword);

    // Find the user in the database
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(401).json({ message: 'Invalid email or password' });
    };

    console.log('user verified');

    hashedPasswordFromDb = user.password;

    console.log(hashedPasswordFromDb);
    console.log(userPassword);

    // Compare passwords
    bcrypt.compare(userPassword, hashedPasswordFromDb, (passwordError, passwordMatch) => {
      if (passwordError) {
        console.error('Error comparing passwords:', passwordError);
        return res.status(500).json({ message: 'Internal server error' });
      }

      console.log(passwordError);
      console.log(passwordMatch);

      if (!passwordMatch) {
        return res.status(401).json({ message: 'Invalid email or password' });
      }

      console.log(passwordMatch);

      // Generate a JSON Web Token (JWT)
      const token = jwt.sign({ email: user.email }, secretKey);

      // Set token expiration date (e.g., 1 hour from now)
      const expirationDate = new Date().getTime() + 3600000;

      // Create a new user instance
      const loggedInUser = {
        firstName: user.firstName,
        lastName: user.lastName,
        email: user.email,
        role: user.role,
        id: user._id,
        _token: token,
        _tokenExpirationDate: expirationDate,
      };

      // Return the authentication response with user details
      const authResponse = new AuthResponseData(loggedInUser);

      res.status(200).json(authResponse);
    });

  } catch (error) {
    console.error('Error:', error); // Log the detailed error message
    console.error('Stack trace:', error.stack); // Log the stack trace

    res.status(500).json({ message: 'Internal server error' });
  }
}); 

i logged things onto the console at intervals to see where the error starts from cause an error isn’t logged onto the console and the code breaks here:

if (!passwordMatch) {
        return res.status(401).json({ message: 'Invalid email or password' });
      }

I tried hashing the user entered password to compare with the stored hashed password and also comparing directly but to no avail.

Vue.Js Routing issues, when visiting product and Visit other links after that, links stack one on top of another

I am building an E-Commerce with Vue.js and Django Rest Framework. Everything is working fine, the only problem is that when I press and visit a product page, then open menu and press any other link it sends me to a blank page and then stacks slug on top of another slug or like link on top of another link which breaks the view.

Lets imagine we visit “lechuga crespa” and then press in menu on “products” it will send you to a blank view and the link would be like that: :8000/lechuga-crespa-verde/productos when it should replace /lechuga-crespa/ by /productos/.

How could I solve that? Thank you.

Here is my router.js:

import { createRouter, createWebHistory } from 'vue-router'
import store from '../store'
import axios from 'axios'

import Home from '../views/Home.vue'
import Products from '../views/shop/Products.vue'
import Product from '../views/shop/Product.vue'
import About from '../views/About.vue'
import Corporate from '../views/Corporate.vue'
import Contact from '../views/Contact.vue'
import ContactThankYou from '../views/ContactThankYou.vue'
import Login from '../views/auth/Login.vue'
import SignUp from '../views/auth/SignUp.vue'
import ResetPassword from '../views/auth/ResetPassword.vue'
import ResetPasswordToken from '../views/auth/ResetPasswordToken.vue'
import ResetPasswordMessage from '../views/auth/ResetPasswordMessage.vue'
import ResetSetNewPassword from '../views/auth/ResetSetNewPassword.vue'
import Account from '../views/auth/Account.vue'
import ComplaintsBook from '../views/ComplaintsBook.vue'
import PrivacyPolicy from '../views/PrivacyPolicy.vue'
import Favorites from '../views/Favorites.vue'
import Cart from '../views/shop/Cart.vue'
import Checkout from '../views/shop/Checkout.vue'

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home,
  },
  {
    path: '/productos',
    name: 'products',
    component: Products,
  },
  {
    path: '/:product_slug/',
    name: 'Product',
    component: Product,
  },
  {
    path: '/nosotros',
    name: 'about',
    component: About,
  },
  {
    path: '/corporativo',
    name: 'corporate',
    component: Corporate,
  },
  {
    path: '/contacto',
    name: 'contact',
    component: Contact,
  },
  {
    path: '/gracias-por-su-mensaje',
    name: 'contactthankyou',
    component: ContactThankYou,
  },
  {
    path: '/favoritos',
    name: 'favorites',
    component: Favorites,
    meta: {
      requireLogin: true
    }
  },
  {
    path: '/carrito',
    name: 'cart',
    component: Cart,
  },
  {
    path: '/finalizar-la-compra',
    name: 'checkout',
    component: Checkout,
    meta: {
      requireLogin: true
    }
  },
  {
    path: '/entrar',
    name: 'login',
    component: Login,
  },
  {
    path: '/registro',
    name: 'register',
    component: SignUp,
  },
  {
    path: '/cuenta',
    name: 'account',
    component: Account,
    meta: {
      requireLogin: true
    }
  },
  {
    path: '/recuperar-cuenta',
    name: 'resetpassword',
    component: ResetPassword,
  },
  {
    path: '/recuperar-cuenta-mensaje',
    name: 'resetpasswordmessage',
    component: ResetPasswordMessage,
  },
  {
    path: '/recuperar/:token_slug/',
    name: 'ResetPasswordToken',
    component: ResetPasswordToken,
  },
  {
    path: '/recuperar-token',
    name: 'resetsetnewpassword',
    component: ResetSetNewPassword,
  },
  {
    path: '/libro-de-reclamaciones',
    name: 'complaintsbook',
    component: ComplaintsBook,
  },
  {
    path: '/terminos-y-condiciones',
    name: 'privacypolicy',
    component: PrivacyPolicy,
  },
]


const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requireLogin) && !store.state.isAuthenticated) {
    next({ name: 'login', query: { to: to.path } });
  } else {
    next()
  }
})

export default router

Here is my product template:

<template>
    <div id="product" class="d-flex flex-column justify-content-between">
        <Header/>
        <div class="d-flex flex-column align-items-center justify-content-center mt-5">
            <div class="container mt-5">
                <nav class="m-0 p-0 mt-5 text-primary" style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E&#34;);" aria-label="breadcrumb">
                    <ol class="breadcrumb">
                        <li class="breadcrumb-item"><a href="#" class="text-decoration-none text-primary">Ecologic</a></li>
                        <li class="breadcrumb-item active" aria-current="page">Productos</li>
                        <li class="breadcrumb-item active" aria-current="page">{{product.name}}</li>
                    </ol>
                </nav>
                <h1 class="text-black text-start p-0 m-0 mb-4 fw-bold fs-3">
                    {{product.name}}
                </h1>
                <div class="row">
                    <div class="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-5 col-xxl-5">
                        <img :src="product.get_image" class="bg-light mb-3 w-100 rounded" alt="">
                    </div>
                    <div class="col-12 col-sm-12 col-md-12 col-lg-6 col-xl-7 col-xxl-7">
                        <div class="d-flex flex-column align-items-start mb-3">
                            <span v-if="product.in_stock" class="form-text mb-2 text-primary">En Stock</span>
                            <span v-else class="form-text mb-2 text-danger">Sin Stock</span>
                            <span class="text-primary fs-5 fw-bold">S/. {{product.price}}</span>
                            <h3 class="fs-6 fw-light mb-4">{{product.name}}</h3>
                            <button v-if="product.in_stock" class="btn btn-primary rounded-pill ps-4 pe-4 mb-2 fs-6 fw-bold text-white" @click="dataToPopup()" data-bs-toggle="modal" data-bs-target="#addProduct">Agregar</button>
                            <button v-else class="btn btn-primary rounded-pill ps-4 pe-4 mb-2 fs-6 fw-bold text-white" disabled>Agregar</button>
                            <!-- <a href="" class="btn btn-outline-primary rounded-pill">
                                <i class="fa-solid fa-heart"></i>
                            </a> -->
                        </div>
                        <div class="d-flex flex-column align-items-start">
                            <div class="w-100 text-start mb-2">
                                <h3 class="fs-6 fw-bold pt-2 pb-0">Descripción:</h3>
                            </div>
                            <div class="w-100 text-start">
                                <p>{{product.description}}</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="container pt-5 pb-5">
            <div class="row">
                <div class="col-12">

                </div>
            </div>
        </div>
        <ProductModal 
            :title='productName'
            :price='productPrice'
            :id='productID'
            :image='productImage'
            :description='productDescription'
        />
        <div class="container mb-5">
            <div class="row">
                <div class="col-sm">
                    <div class="rounded-5 p-5 bg-primary text-start">
                        <h2 class="text-white fw-bold">
                            ¿Usted es mayorista o tiene negocio de rubro alimenticio?
                        </h2>
                        <p class="text-white fw-lighter">Tenemos una gran variedad de productos que ofrecemos para los negocios a nivel nacional. Los invitamos a ver nuestra oferta y solicitar la cotización.</p>
                        <router-link to="corporativo" class="btn bg-white rounded-pill fw-bold text-primary">Ver oferta corporativa</router-link>
                    </div>
                </div>
            </div>
        </div>
        <Footer/>
    </div>
</template>

<script>
// @ is an alias to /src
import Header from '@/components/Header.vue'
import Footer from '@/components/Footer.vue'
import ProductModal from '@/components/ProductModal.vue'
import axios from 'axios'

export default {
    name: 'Product',
    components: {
        Header,
        Footer,
        ProductModal,
    },
    data() {
        return {
            product: {},
            quantity: 1,

            // DATA TO SEND TO MODAL COMPONENT
            productName: '',
            productPrice: '',
            productID: 0,
            productImage: '',
            productDescription: '',
        }
    },
    mounted() {
        this.getProductDetails()
    },
    methods: {
        async getProductDetails() {
            //   const category_slug = this.$route.params.category_slug
            const product_slug = this.$route.params.product_slug

            await axios
                .get(`/api/v1/productos/${product_slug}`)
                .then(response => {
                    this.product = response.data
                    document.title = this.product.name + ' | PeruLab'
                })
                .catch(error => {
                    console.log(error)
                })
        },
        dataToPopup() {
            this.productName = this.product.name
            this.productPrice = this.product.price
            this.productID = this.product.id
            this.productImage = this.product.get_image
            this.productDescription = this.product.description
        },
    },
}
</script>

<style scoped>
#product {
    min-height:100vh;
}
</style>

useNavigate not working react-router-dom v6 but works when i press a button

Im using react-router v6, the useNavigate() hook, nothing happens when I run it in a function. I see my console log output.

If I press the button, it navigates successfully. How do I get the navigate() to work in the logic part of the code?

import { useNavigate } from 'react-router-dom'
import { getAuth } from 'firebase/auth'

function Loading() {
  const navigate = useNavigate()

  getAuth().onAuthStateChanged(user => {
    if (user === null) {
      navigate('/signin')
    } else {
      console.log('i see this in the console')
      navigate('/dashboard')
    }
  })

  return (
    <Button onClick={() => navigate('/home')}>Press button</Button>
  )
}

JQuery Function to sort list alphabetically in is not working, tried various variations

I have been trying to sort this list within a div alphabetically, but either the list disappears, or nothing changes. Any tips please?

//Sort
var alphabeticallyOrderedDivs = $('.list-group-item').sort(function(a, b) {
  return String.prototype.localeCompare.call($(a).data('sortLis').toLowerCase(), $(b).data('sortList').toLowerCase());
});

var container = $("#assignedMemberList");
container.detach().empty().append(alphabeticallyOrderedDivs);
$('body').append(container);


function clearSelectedItem() {
  $.each($('#assignedMemberList .list-group-item'), function(idx, item) {
    if ($(item).hasClass('active')) {
      $(item).removeClass('active');
    }
  });
}
<div class="panel-body assign-member-panel-body" id="assignMemberPanelBody">
  <div class="row">
    <div class="col-md-12">
      <input type="text" placeholder="Search" id="assignedMemberTxt" class="form-control" />
      <div id="listAssignPatientContainer" class="overflowAuto well well-sm" style="height: 300px">
        <div id="assignedMemberList" class="list-group">
        </div>
      </div>
    </div>
  </div>
</div>

React useState hook array only saves data after API call and replaces previously stored state. What am I doing wrong?

I am a freelancer who recently started development (currently working with nextjs and reactjs). I am having issues in understanding why the useState hook array won’t update data correctly.

You can find the code and console logs below:

I am using one useState hook to store arrays in two different positions in same function, once before the api call and next after the api call.

Till the api is called the state before the call is stored correctly but after the api call new state is stored as well but it replaces the previously stored state and no matter how many times i run the array would only store all the data after the api call and the one stored before would be replaced.

For context i am trying to make a chat-box.

Kindly anyone help me understand and resolve the issue.


    const [userInput, set_userInput]= useState(false)
    const [outputValue, set_outputValue]= useState(false)
    const [answer, set_answer]= useState([])
    const [history, set_history]= useState([])
    const [newMessage, setNewMessage] = useState('');
    const [messages, setMessages] = useState([])

    console.log("outside of function",messages)

    async function UserInputAllow(){
        set_userInput(true)
        set_outputValue(false)
        const input = document.getElementById("input").value;
        // console.log("before user save",messages.length)
        const usernewId = messages.length + 1;
        setMessages([...messages, { id: usernewId,  role: "user", text: input }]);

        try {
          const  data = {
                key:input
            }
          
console.log("before call",data)
            const resp = await Chat_Usecase(data)
            if (resp.status === 200 || resp.status === 201){
                console.log("system chat reply",resp)
                console.log("user save",messages.length)
                    const newId =  messages.length + 1;
                    setMessages([...messages,  { id: newId,  role: "assist", text: resp.data }]);
            }
            console.log("convo history",messages)
            
        } catch (error) {
            
        }
    }
    console.log("below func",messages)

```[[enter image description here](https://i.stack.imgur.com/CKFP0.png)](https://i.stack.imgur.com/toHYz.png)

Why is my discord.js bot sending a ‘connect ECONNREFUSED’ error when I try to turn it on?

I’m writing a bot for discord using discord.js, and for some reason the bot just turned off overnight and sends an error when I turn it on. The error:

(node:613) UnhandledPromiseRejectionWarning: FetchError: request to https://discord.com/api/v7/gateway/bot failed, reason: connect ECONNREFUSED ***.***.***.***:443
    at RequestHandler.execute (/home/runner/Galen/node_modules/discord.js/src/rest/RequestHandler.js:93:15)
(node:613) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:613) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Any help appreciated!

I havn’t tried anything yet. The error does not tell me if it’s coming from a line of code, so I don’t know what to do.

How to retrieve and assign existing class to element without text content or class?

I am trying to make a calendar that is made as a table and does not have text content or class assigned yet (besides <thead>).

This is what it initially looks like:

      <div className="calendar">
        <header>

          <h2>{curMonth()}</h2>

          <button className="btn-prev fontawesome-angle-left" onClick={changePrevMonth}></button>
          <button className="btn-next fontawesome-angle-right" onClick={changeNextMonth}></button>

        </header>

        <table>

          <thead>

            <tr className="dow">

              <td>Su</td>
              <td>Mo</td>
              <td>Tu</td>
              <td>We</td>
              <td>Th</td>
              <td>Fr</td>
              <td>Sa</td>

            </tr>

          </thead>

          <tbody>

            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>

            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>

          </tbody>

        </table>
      </div>

For <tbody>, I would like for it to use calendar-dates npm package which returns the accurate day of the week for the last a number of days from the previous month, the b number of days for the current (focused) month, and the first c number of days from the following month.

My issue is when getting the tbody tr parts using querySelectorAll(), it returns null. Is there any way I can retrieve and assign class to the <td> portion that is by default empty and no class? Later, it will be able to change it if the text (date) exists and already has class.

Calculate / update a dynamic value in an attribute in Vue

I am new to Vue and I have a hard time trying to figure out how I can update dynamic values.

I have a list of items. The length of all items together is totalResults. I would now like to substract values from totalResults and update what is left. So let’s say I’d have two lists with a certain length: itemsA.length = 50 and itemsB.length = 25 (in real life I have a lot of lists).

I am trying:

<span :count="counttotal(totalResults - itemsA.length)">Count: {{ count }} </span>

{{ count }} should now be 50, but totalResults should be as well.

Next I’m trying to substract B:

 <span :count="counttotal(totalResults - itemsB.length)">Count: {{ count }} </span>

{{ count }} should now be 25, because totalResults = totalResults - itemsA.length - itemsB.length.

I am trying this method:

methods: {
counttotal(val) {
        this.count = this.count - val;
    }
  }

I am getting this error: you may have an infinite update loop in a component render function

I can solve it without using a method. But I am pretty sure this is not how it’s meant.

<span :count="totalResults - itemsA.length - itemsB.length">Count: {{ count }} </span>
<span :count="totalResults - itemsA.length - itemsB.length - itemsC.length">Count: {{ count }} </span>
<span :count="totalResults - itemsA.length - itemsB.length - itemsC.length - itemsD.length">Count: {{ count }} </span>

I can set and update totalResults in local storage, but for such a simple task this feels like a workaround.

Any suggestions how I can update totalResults each time I am calling the counttotal method?

Make window.onbeforeunload executed on page close and not on page refresh

I want to clear my local storage after closing the browser, for that I control all active tabs using sessionStorage

so, my App.js looks like this:

    window.onload = () => {
        var tabID = sessionStorage.getItem("tab_id");
        if (tabID === null) {
            var hash = Math.random(10**5).toString(36)
            sessionStorage.setItem("tab_id", hash);
            var allTabs = localStorage.getItem("all_tabs");
            if (allTabs ==null || allTabs==''){
                console.log(1)
                allTabs=[]
            }
            else{
                console.log(1, allTabs)
                allTabs = allTabs.split(',');
            }
            console.log(allTabs)
            allTabs.push(hash)
            console.log(hash, 'local', allTabs)
            localStorage.setItem("all_tabs", allTabs);
        }
    }

    window.onunload  = () => {
        var tabID = sessionStorage.getItem("tab_id");
        var allTabs = localStorage.getItem("all_tabs");
        var locItemsArr = allTabs.split(',');

        var ind = locItemsArr.indexOf(tabID)
        locItemsArr.splice(ind,1)
        localStorage.setItem("all_tabs", locItemsArr.toString());

        if (localStorage.getItem("all_tabs") == "" ) {
            console.log('clear')
            localStorage.clear()
        }
    }

However, I didn’t took into account the fact that onunload will also be triggered when the page is updated. Is there any way to understand if the page is closing or just being updated to clear localStorage only after closing?

Migration problem for mui chips not to be rounded by default

I am trying to migrate mui4 to mui5. There is a weird behaviour that chip component does.Normally chips should be rounded by default.However, when I add onClick function it makes chips square.When I remove the onClick function, it turns rounded.Can anyone knows why this is happening?

<Chip
icon={icon}
disabled={!showAnalytics}
style={style}
label={name}
onClick={() => onChipClick(id)}
/>