Bootlint is complaining that my bootstrap col isn’t a child of a row—but it is?

When I run the bootlint bookmarklet or extension it give me this error:

Columns (`.col-*-*`) can only be children of `.row`s or `.form-group`s

but my column is the direct child of a row. This is basically the whole page, minus a few dotpoints. What am I missing? Is it because I’m using version 3?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>foo</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <div class"row">
        <div class="col-md-12">
            <h1>
                bar
            </h1>
            <ul>
            [snip]
            </ul>
        </div>
    </div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js">
</script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js">
</script>
</body>
</html>

Javascript using event listener to put value in an input box

const one = document.getElementById("one");
// const input = document.getElementById("input");
one.addEventListener('click', function() {
  // document.forms[0].input.value = '1';

  document.getElementById("input").value = 1;
});
main {
  display: grid;
  grid-template-columns: 60px 60px 60px;
  grid-template-rows: 60px 60px 60px 60px;
}

#clear {
  grid-column: 2/4;
  grid-row: 4/5;
  border: 1px solid blue;
}

div {
  border: 1px solid blue;
  text-align: center;
  font-size: 24px;
  background-color: lightgreen;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>Document</title>
</head>

<body>
  <form name="form1">
    <input id="input" name="input">
  </form>
  <main>
    <div id="one">1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>0</div>
    <div id="clear">CLEAR</div>
  </main>
</body>

</html>

I tried creating buttons using css grid and javascript to put a value to an input box but it doesn’t work. I tried this:

document.getElementById("one").value = 1; 

I also tried

document.forms[0].input.value = 1

This is like a calculator problem. You input numbers to an input box by clicking on the number buttons.

router.refresh() from next/navigation doesnt working

Here in my component I have onSubmit which every time a task is added, it must reload the page, but it is not reloading after the onSubmit function is called, I have already checked and I do not receive errors in the console, even the toast is sent, but the refresh () is not done

"use client"

import { zodResolver } from "@hookform/resolvers/zod"
import { useRouter } from "next/navigation"
import React, { useRef, ReactNode } from "react"
import { useForm } from "react-hook-form"
import { upsertKanbanTaskSchema } from "../schema"
import { upsertKanbanTask } from "./actions"
import { toast } from "@/components/ui/use-toast"
import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet"
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select"
import { z } from "zod"
import { Task } from "../types"

type KanbanUpsertSheetProps = {
  children?: React.ReactNode
  defaultValue?: Task
}

export function KanbanAddSheet({ children }: KanbanUpsertSheetProps) {

  const ref = useRef<HTMLDivElement>(null)
  const router = useRouter()

  const form = useForm({
    resolver: zodResolver(upsertKanbanTaskSchema)
  })
  const onSubmit = form.handleSubmit(async (data) => {
    await upsertKanbanTask(data)
    router.refresh()

    ref.current?.click()
    toast({
      title: 'Sucesso!',
      description: 'Sua tarefa foi adicionada com sucesso.',
    })
  })
  return (
    <Sheet>
      <SheetTrigger asChild>
        <div ref={ref}>{children}</div>
      </SheetTrigger>
      <SheetContent>
        <Form {...form}>
          <form onSubmit={onSubmit} className="space-y-8 h-screen">
            <SheetHeader>
              <SheetTitle>Adicionar Tarefas</SheetTitle>
              <SheetDescription>
                Preencha os campos abaixo para adicionar uma nova tarefa.
              </SheetDescription>
            </SheetHeader>
            <FormField
              control={form.control}
              name="title"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Título</FormLabel>
                  <FormControl>
                    <Input placeholder="exemplo: Trabalho" {...field} />
                  </FormControl>
                  <FormDescription>
                    Esse é o título da sua tarefa.
                  </FormDescription>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="description"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Descrição</FormLabel>
                  <FormControl>
                    <Input placeholder="exemplo: Enviar Emails para Cliente" {...field} />
                  </FormControl>
                  <FormDescription>
                    Esse é a descrição da sua tarefa.
                  </FormDescription>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="status"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Status</FormLabel>
                  <FormControl>
                    <Select {...field}>
                      <SelectTrigger className="w-full">
                        <SelectValue placeholder="Selecione um Status" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectGroup>
                          <SelectLabel>Status</SelectLabel>
                          <SelectItem value="a-fazer">A Fazer</SelectItem>
                          <SelectItem value="fazendo">Fazendo</SelectItem>
                          <SelectItem value="feito">Feito</SelectItem>
                        </SelectGroup>
                      </SelectContent>
                    </Select>
                  </FormControl>
                </FormItem>
              )}
            />
            <SheetFooter className="mt-auto">
              <Button type="submit">Adicionar Tarefa</Button>
            </SheetFooter>
          </form>
        </Form>
      </SheetContent>
    </Sheet>
  )
}

I’ve tried to force the refresh in several ways, but to no avail.

const onSubmit = form.handleSubmit(async (data) => {
    await upsertKanbanTask(data)
    
    // force update
    router.push(router.asPath)

    ref.current?.click()
    toast({
        title: 'Sucesso!',
        description: 'Sua tarefa foi adicionada com sucesso.',
    })
})

How to remove duplicates from an array in JavaScript? [duplicate]

I want to transform this array into a new array that contains only unique values. I’ve tried a few methods, but I’m not sure which one is the most efficient and commonly used in modern JavaScript.
Using a For Loop: I manually checked each element and pushed unique values to a new array.This works but feels cumbersome and might not be the most efficient approach.
Using Set: I learned that Set automatically removes duplicates, so I tried this:This method is concise and leverages modern JavaScript features, but I’m curious about its performance compared to other methods.
Using Filter: I also tried using filter() with indexOf():This approach also works but involves using the indexOf method, which might not be the most efficient for large arrays.
Using Reduce: I found another method using reduce() to accumulate unique values:This method is more functional and leverages reduce(), but I’m not sure if it offers any performance benefits over the other methods.

How can we avoid player position allocated in same team during random team generation

Would like to generate two or three teams based on selection ie ( 7-aside or 8- aside) . While doing the generation for 3 teams, for a 7 side game with 20 players, D-level players or F level player are not evenly distributed between teams based on Levels.

Could someone please advise the issue here ?

Extra players need to display as Substitutes:
code:

  const [input, setInput] = useState('');
  const [team1, setTeam1] = useState([]);
  const [team2, setTeam2] = useState([]);
  const [team3, setTeam3] = useState([]);
  const [subs, setSubs] = useState([]);
  const [savedTeams, setSavedTeams] = useState(JSON.parse(localStorage.getItem('savedTeams')) || []);
  const [numTeams, setNumTeams] = useState(2);
  const [playersPerSide, setPlayersPerSide] = useState(7);
  const [error, setError] = useState(null);
  const captureRef = useRef(null);
 

  useEffect(() => {
    localStorage.removeItem('savedTeams');
  }, []);

  const sanitizeInput = (input) => {
    return input.replace(/[^a-zA-Z0-9-.ns]/g, '');
  };

  const handleInputChange = (e) => {
    const sanitizedInput = sanitizeInput(e.target.value);
    setInput(sanitizedInput);
  };

  const handleNumTeamsChange = (e) => {
    setNumTeams(Number(e.target.value));
  };

  const handlePlayersPerSideChange = (e) => {
    setPlayersPerSide(Number(e.target.value));
  };

  const splitTeams = () => {
    if (!input.trim()) {
      setError('The input field cannot be empty. Please enter player names!');
      return;
    }

    const players = input
      .split('n')
      .map(player => player.trim())
      .filter(player => player)
      .map(player => player.replace(/^d+.s*/, ''));

    // Extract goalkeepers and outfield players
    const goalkeepers = players.filter(player => player.includes('GK'));
    const outfieldPlayers = players.filter(player => !player.includes('GK'));

    // Identify repeat players (marked with -R)
    const repeatPlayers = players.filter(player => player.includes('-R')).map(player => player.replace('-R', ''));
    const uniqueRepeatPlayers = [...new Set(repeatPlayers)];

    // Remove the repeat players from the list if exists
    const cleanedPlayers = players.filter(player => !player.includes('-R'));

    // Calculate the total number of required players
    const totalRequiredPlayers = playersPerSide * numTeams;
    const totalAvailablePlayers = cleanedPlayers.length + uniqueRepeatPlayers.length;

    // Check if we have enough players, including the repeat player
    
    // if (totalAvailablePlayers < totalRequiredPlayers) {
    //   setError(`Insufficient players. You need at least ${totalRequiredPlayers} players for ${numTeams} teams.`);
    //   return;
    // }

    // Initialize teams and substitutes
    const mainTeams = Array.from({ length: numTeams }, () => []);
    const shuffledOutfieldPlayers = outfieldPlayers.sort(() => Math.random() - 0.5);
    const availablePlayers = [...cleanedPlayers, ...uniqueRepeatPlayers];

    // Distribute goalkeepers among teams
    const usedGoalkeepers = new Set();
    goalkeepers.forEach(gk => {
      if (usedGoalkeepers.size < numTeams) {
        for (let i = 0; i < numTeams; i++) {
          if (mainTeams[i].filter(player => player.includes('GK')).length === 0 && !usedGoalkeepers.has(gk)) {
            mainTeams[i].push(gk);
            usedGoalkeepers.add(gk);
            break;
          }
        }
      }
    });

    // Distribute outfield players among teams
    let currentTeamIndex = 0;
    shuffledOutfieldPlayers.forEach(player => {
      if (mainTeams[currentTeamIndex].length < playersPerSide) {
        mainTeams[currentTeamIndex].push(player);
      }
      currentTeamIndex = (currentTeamIndex + 1) % numTeams;
    });

    // Ensure repeat players are placed correctly in the white team
    const whiteTeamIndex = numTeams === 3 ? 2 : 1; // Assuming white team is the last team if there are 3 teams
    const whiteTeamPlayers = new Set(mainTeams[whiteTeamIndex]);
    uniqueRepeatPlayers.forEach(player => {
      if (!whiteTeamPlayers.has(player)) {
        if (mainTeams[whiteTeamIndex].length < playersPerSide) {
          mainTeams[whiteTeamIndex].push(player);
          whiteTeamPlayers.add(player);
        }
      }
    });

    // Collect all players currently in teams
    const allPlayersInTeams = mainTeams.flat();
    // Calculate substitutes
    const substitutePlayers = availablePlayers.filter(player => !allPlayersInTeams.includes(player));

    setTeam1(mainTeams[0]);
    setTeam2(mainTeams[1]);
    if (numTeams === 3) setTeam3(mainTeams[2]);
    setSubs(substitutePlayers);
    setError(null);

    const newSavedTeams = [...savedTeams, { team1: mainTeams[0], team2: mainTeams[1], team3: mainTeams[2] || [], subs }];
    setSavedTeams(newSavedTeams);
    localStorage.setItem('savedTeams', JSON.stringify(newSavedTeams));
  };

  const sortPlayers = (players) => {
    return players.sort((a, b) => {
      const [aCategory, aLevel] = a.split('-').slice(1);
      const [bCategory, bLevel] = b.split('-').slice(1);

      const categoryOrder = ['GK', 'D', 'M', 'F'];
      const levelOrder = ['A', 'B', 'C', 'D'];

      if (aCategory !== bCategory) {
        return categoryOrder.indexOf(aCategory) - categoryOrder.indexOf(bCategory);
      }

      return levelOrder.indexOf(aLevel) - levelOrder.indexOf(bLevel);
    });
  };

  const downloadImage = () => {
    if (captureRef.current) {
      html2canvas(captureRef.current).then(canvas => {
        const link = document.createElement('a');
        link.href = canvas.toDataURL('image/png');
        link.download = 'teams.png';
        link.click();
      });
    }
  };

  const deleteSavedTeam = (index) => {
    const newSavedTeams = savedTeams.filter((_, i) => i !== index);
    setSavedTeams(newSavedTeams);
    localStorage.setItem('savedTeams', JSON.stringify(newSavedTeams));
  };

  const loadSavedTeam = (index) => {
    const team = savedTeams[index];
    setTeam1(team.team1);
    setTeam2(team.team2);
    setTeam3(team.team3);
    setSubs(team.subs);
  };

[![enter image description here][1]][1]

Input players:

1.Done-GK-A
2.Jerril-D-A
3.Max-D-B
4.Mikhail-M-B
5.Sante-F-A
6.Rodie-M-A
7.Wanner-M-A
8.Aaron-D-A
9.Frank-F-A
10.Milton-GK-B
11.Ferris-M-B
12.Rashes-F-A
13.Sajin-GK-A
14.Jacob-M-A
15.Johns-M-A-R
16.Lewis-F-B
17.Aabel-D-A
18.Melvin-D-A
19.Reymond-M-B
20.Delvin-F-A

CodeSandbox >>> https://codesandbox.io/p/sandbox/teamgen-8nzrs5

Rules need to follow / align while doing the team split:

 1. Split into two teams or three teams for a 7 - aside or 8 - aside game.
 2. Allocate GK into three teams, no two GK in the same team, same with other position not all defence or mid or forward players in one team
 3. Display in the below order, First Gk , then Defence, then Mid and finally Forward players. Positions- Gk, D, M and F are the positions 
 4. Evenly split Level-A player for any position between teams. A, B, C and D are the levels 
 5. If there are only 20 players available for a 7 - aside game, and if -R is given for a player input  >> Repeat that player in the third team. So eventually that player will be available in two teams. 

Generated teams: ( see Defense player got allocated in White and Black teams)

Team Red
Done-GK-A
Rodie-M-A
Jacob-M-A
Mikhail-M-B
Frank-F-A
Rashes-F-A
Lewis-F-B

Team Black
Milton-GK-B
Jerril-D-A
Melvin-D-A
Wanner-M-A
Johns-M-A-R
Reymond-M-B
Sante-F-A

Team White
Sajin-GK-A
Aabel-D-A
Aaron-D-A
Max-D-B
Johns-M-A
Ferris-M-B
Delvin-F-A

How to prevent parcel from moving images around?

Trying to use webgl to render a texture, and I am using some npm libraries so I am using .cjs files and using parcel to run it. When I try to get the image from my resources file it doesnt work because parcel moves the image into the project directory and also changes the image name. Is there a way to prevent this from happening?

the file structure looks like this:

index.html
index.cjs
src/
  | renderer.cjs
  | resources/
  |   | image.png

but when I run it, parcel changes it to this:

index.html
index.cjs
renderer.cjs
image.86ccfd9d.png

ChatGPT didnt help either

Is my function in the correct scope? What is the problem with it? [closed]

Link to error

So I am currently working on the Tic Tac Toe game of the odin project and having problems. I want to set up a function running the game itself and to do that I created a function called Game. In it I have a function I want to discuss. This.currentPlayer. Is the while loop under it correctly scoped because when I try to run the code myself I get a type error saying that cheese.markPosition is not a function? Is my function correctly scoped? How do I go about accessing the variables of a function inside another function like I have already done in the Player function?

function createGameBoard(){
    let spotOne = []
    let spotTwo = []
    let spotThree = []
    let spotFour = []
    let spotFive = []
    let spotSix = []
    let spotSeven = []
    let spotEight = []
    let spotNine = []
    let spots = [spotOne,spotTwo,spotThree,spotFour,spotFive,spotSix,spotSeven,spotEight,spotNine]
    return {spots,spotOne,spotTwo,spotThree,spotFour,spotFive,spotSix,spotSeven,spotEight,spotNine}
}

function Player(name, marker){
    this.name = name;
    this.marker = marker;
    this.Playing = false
    this.sayMarker = function(){
        console.log(`my marker is ${this.marker}`);
    };
    this.markPosition = function(gameBoard,spot){
        
        switch(spot){
            case 1:
                if((gameBoard.spotOne.length) == 0){
                    gameBoard.spotOne.push(this.marker)
                    
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotOne.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 2:
                if((gameBoard.spotTwo.length) == 0){
                    gameBoard.spotTwo.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotTwo.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 3:
                if((gameBoard.spotThree.length) == 0){
                    gameBoard.spotThree.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotThree.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 4:
                if((gameBoard.spotFour.length) == 0){
                    gameBoard.spotFour.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotFour.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 5:
                if((gameBoard.spotFive.length) == 0){
                    gameBoard.spotFive.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotFive.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 6:
                if((gameBoard.spotSix.length) == 0){
                    gameBoard.spotSix.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotSix.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 7:
                if((gameBoard.spotSeven.length) == 0){
                    gameBoard.spotSeven.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotSeven.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 8:
                if((gameBoard.spotEight.length) == 0){
                    gameBoard.spotEight.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotEight.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
            case 9:
                if((gameBoard.spotNine.length) == 0){
                    gameBoard.spotNine.push(this.marker)
                    console.log(`marking position #${spot} with ${this.marker}`)
                }
                else if((gameBoard.spotNine.length > 0)){
                    console.log(`Cannot mark the same spot twice in Tic Tac Toe`)
                }
                console.log(gameBoard.spots)
                break;
        }

    }
}
function Game(Gameboard, ...Players){
    this.players = Players
    this.currentPlays = 0
    this.currentPlayer = function(){
        randomNumber = (`${Math.floor(Math.random() * 2)}`)
        return Players[randomNumber].name
    }
    while(this.currentPlays < 10){
        ++this.currentPlays
        cheese = this.currentPlayer()
        Play = prompt(`Where shall ${cheese} Play?`)
        cheese.markPosition(Gameboard,Play)
    }
    this.Game = Gameboard
   
}

const FelaF = new Player("FelaF","X")
const Jimmy = new Player("Jimmy", "O")
const James = new Player("James", "X")
Gameboard1 = createGameBoard()
FelaF.markPosition(Gameboard1, 7)
console.log(FelaF.name)
Jimmy.markPosition(Gameboard1, 7)
const G1 = new Game(Gameboard1, Jimmy, FelaF)
console.log(G1.currentPlayer())

Instead of a constructor function I tried to convert the Game function into a factory function with no avail. Please help?

Converting JSON to Base64 using JavaScript without dependencies

I’m after reading a few posts on the subject, a few of which suggested atob/btoa are too buggy to be used in prod. mdn has no deprecation badge for them. I need a zero dependency JavaScript solution working with reasonably new browsers, I’m using it for JWK encoding. I tested atob/btoa with a few JWKs and it worked just fine, so did C# code decoding base64 strings encoded on a client. Can anyone in the know confirm if atob/btoa are safe to be used in prod or is there an alternative which’d work without node.js modules.

RangeError: Array buffer allocation failed after multiple page refreshes despite sufficient memory

I’m encountering a RangeError: Array buffer allocation failed error in my JavaScript application after refreshing the page multiple times. The error occurs even though the memory usage appears to be well within limits. Here are the details from the last time I hit this error:

JavaScript Heap Size Limit: 4,294,705,152 bytes (approximately 4.29 GB)
Total JavaScript Heap Size: 300,268,829 bytes (approximately 300 MB)
Used JavaScript Heap Size: 292,110,613 bytes (approximately 292 MB)

Despite using less than 10% of the available memory, the error occurs after about 5 page refreshes. I have to clear the browser data and refresh the page to temporarily resolve the issue (ctrl-shift-r in chrome for hard refresh).

From my research into the issue, I’m guessing that it has to do with memory fragmentation, but that still seems pretty absurd to me that the memory is so fragmented that it can’t find a contiguous block of around 100mb when there are still gigabytes available. Unfortunately everything I found online never had a real resolution beyond “just use smaller array buffers but there’s no way to know exactly how much.

Some context on what I’m working on:

I’m playing around with generating and rendering simplex noise with web workers. I use shared array buffers to get that data between the workers and the main thread without incurring the cost of serializing that data.

If I’m rendering a 5000×5000 image of noise, I need a shared array buffer large enough to hold 25,000,000 f32s, which is about 100mb. Seeing as I have “4gb available”, I figured this is no big deal to hold a few of these at a time. Unfortunately if I do a normal reload too many times I hit the error above.

If I’m right about the fragmentation, I could break this up into a bunch of smaller buffers. Unfortunately with that I think i would lose some performance because I can no longer just loop over the entire map in one contiguous block (new to this so not positive on that). The other problem with this is I don’t know what that magic number is where I’ll stop hitting this error. I could put a try catch around all buffer allocations and if one fails, split that buffer into 4 or something, but that would add a lot of complexity to my project.

What else can I do about this?

Br tag doesn’t work with AppendChild() and display: flex

I am making a to-do list program where after every checkbox, there should be a new line. But the br function doesn’t work and I think it has to do with the CSS text, where the code is display: flex. Have a look:(Javascript)

document.addEventListener('DOMContentLoaded', () => {
const textareaEle = document.getElementById('j');
textareaEle.addEventListener('input', () => {
    textareaEle.style.height = 'auto';
    textareaEle.style.height = `${textareaEle.scrollHeight}px`;
});
function myFunction(){
const dif = document.getElementById("dif");
const div = document.getElementById("copy");
const sauce = document.getElementById("sauce")
const textareaEle = document.getElementById('j');
let checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox", "class", "checkbox");
let paragraph = document.createElement("p");
paragraph.setAttribute("class", "checkbox");
let konq = document.createTextNode(textareaEle.value);
let line = document.createElement("br");
paragraph.appendChild(konq);
sauce.appendChild(checkbox);
sauce.appendChild(paragraph);
sauce.appendChild(line);
}

CSS

#sauce{
display: flex;

}

MVP pattern implementation in ReactJs, caveats?

I’m trying different MVP implementations in React, to solve the issue of Presenter sending data to View in adhoc manner.

Here is what I came to:

The state in the wrapper index.jsx is used to get the data from presenter to View.
So that View doesn’t have to handle getting data from presenter in its own state or subscribe to streams.

What considerations or caveats one should think of?

src
  -Counter
        -index.jsx
        -presenter.js
        -View.jsx
  -App.jsx

index.jsx

import React, { useState, useMemo } from 'react';

import Presenter from './presenter';
import View from './View';

export default function index(props) {
  // presenterData is a state updated by presenter to send its content to View.
  const [presenterData, setPresenterData] = useState({});

  // setPresenterData is sent to presenter to update whatever need updating.
  const presenter = useMemo(() => {
    return new Presenter(setPresenterData);
  }, []);
  // View takes presenter to talk to, and takes presenterData to read
  // upon change.
  return <View {...props} presenter={presenter} presenterData />;
}

presenter.js

export default class Presenter {

  // presenter gets setPresenterData to update parent component thus the view.

  constructor(setData) {

    // the props is all the variables that we want to communicate to View
    this.props = {
      text: 'aus',
      numbers: 123,
      obj: {
        a: 1,
        b: 2,
      },
    };
    this.interval;
    this.setData = setData;
  }

  inc = () => {
    this.interval = setInterval(() => {

      // whenever props (data to View) is changed
      // setPp is called to update View.

      this.props.numbers++;
      this.setData({ ...this.props });

    }, 1000);
  };

  stop = () => {
    clearInterval(this.interval);
  };
}

View.jsx

import React from 'react';

export default function View(props) {

  // this way the view doesn't need to keep state for presenter variables.
  // Nor does it need to subscribe or send callbacks.
  // Even cleanup is already arranged by parent component.

  return (
    <div>
      <div>{props.pp.numbers}</div>
      <button onClick={props.presenter.inc}>aaaa</button>
      <button onClick={props.presenter.stop}>Stop</button>
    </div>
  );
}

Render Items in Component Not the whole component

am getting data from websocket for real live update am updating Inside Popup of leaflet map, useEffect start re-render to get new data so the Popup disappears and I need to click again on the mark on map to see updated data, All I want that the data changes without disappearing of the Popup.
Here is the code of the Component called Positions which carry change of Data and Markers on map.

import React, { useEffect, useState } from "react";
import { useGetAllPositionsQuery } from "../../Redux/service/Positions";
import MarkerClusterGroup from "react-leaflet-cluster";
import { Marker, Popup } from "react-leaflet";
import { Icon } from "leaflet";
import PositionsPopups from "./Positions-Popups/PositionsPopups";
import { useGetWebSocketDataQuery } from "../../Redux/service/Websocket";

export default function Positions() {
  const { data, isLoading } = useGetAllPositionsQuery();
  let [position, setPosition] = useState();

  const { data: ws, error, isLoading: wsLoading } = useGetWebSocketDataQuery();
  useEffect(() => {
    if (ws) {
      ws?.positions?.map((i) => {
        setPosition([i]);
        console.log(i);
      });
    }
  }, [ws]);
  Icon.Default.mergeOptions({
    iconUrl: "https://freesvg.org/img/car_topview.png",
    iconSize: [32, 32], // size of the icon
    shadowAnchor: [4, 62], // the same for the shadow
    popupAnchor: [-3, -20], // point from which the popup should open relative to the iconAnchor
  });

  return (
    <>
      <MarkerClusterGroup chunkedLoading>
        {position?.map((mark) => (
          <Marker key={mark.id} position={[mark.latitude, mark.longitude]}>
            <Popup closeOnEscapeKey>
              <PositionsPopups mark={mark} />
            </Popup>
          </Marker>
        ))}
      </MarkerClusterGroup>
    </>
  );
}

Code of PositionsPopups Component

import React, { useEffect, useState } from "react";
import PositionsPopupsDetails from "./PositionsPopupsDetails";

export default function PositionsPopups({ mark }) {
  const [popupData, setPopupData] = useState(mark);

  useEffect(() => {
    setPopupData(mark);
  }, [mark]);
  return (
    <>
      <div className="device-popup">
        {" "}
        <PositionsPopupsDetails title="fix time" item={popupData.fixTime} />
        <PositionsPopupsDetails
          title="speed"
          item={popupData.speed.toFixed(2) + ` KM`}
        />
        <PositionsPopupsDetails title="address" item={popupData.address} />
        <PositionsPopupsDetails
          title="total distance"
          item={Math.round(popupData.attributes.totalDistance / 1000) + ` KM`}
        />
      </div>
    </>
  );
}

Am trying to only re-render the data in popups not the whole popup component

Why are my stripe webhook session details saying they are undefined?

I am creating a stripe checkout session in my development mode, that is successfully sending information to my webhook, and when I print out my session details, it successfully prints out all the information from the session. The weird part is though, that when I try to access an individual piece of information so I can save it in my backend with prisma, it says the information is undefined when i console.log it out. It’s so weird I can see the whole thing, but not the individual information. What am I doing wrong and how can I access the individual lines in my Next.js program?

Here is my webhook code

import Stripe from "stripe";
import { stripe } from "@/lib/stripe";
import { headers } from "next/headers";
import { NextResponse } from "next/server";
import prisma from "@/lib/db/prisma";
import { OrderItem } from "@prisma/client";
import { createCart, getCart } from "@/lib/db/cart";
import { revalidatePath } from "next/cache";

export async function POST(req: Request) {
  const cart = (await getCart()) ?? (await createCart());
  const body = await req.text();
  const signature = headers().get("Stripe-Signature") as string;

  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      process.env.STRIPE_WEBHOOK_SECRET!,
    );
  } catch (error) {
    return new NextResponse("Invalid signature", { status: 400 });
  }

  const session = event.data.object as Stripe.Checkout.Session;

  if (event.type === "charge.succeeded") {
    console.log("*********************************************************");
    console.log(session.shipping_details?.address?.state);
    console.log("*********************************************************");
    const paymentIntent = event.data.object;

    const userId = paymentIntent.metadata.userId;
    const {
      name,
      address,
      aptNumber,
      city,
      state,
      zipCode,
      country,
      paymentMethod,
      totalInCents,
      taxInCents,
      cartItems,
    } = paymentIntent.metadata;

    try {
      await prisma.$transaction(async (prisma) => {
        // Create the order
        const order = await prisma.order.create({
          data: {
            userId,
            name,
            address,
            aptNumber,
            city,
            state,
            zipCode,
            country,
            paymentMethod,
            totalInCents: parseInt(totalInCents),
            taxInCents: parseInt(taxInCents),
          },
        });

        // Create order items
        const orderItems = JSON.parse(cartItems).map((item: OrderItem) => ({
          productId: item.productId,
          productName: item.productName,
          price: item.price,
          quantity: item.quantity,
          orderId: order.id,
        }));

        await prisma.orderItem.createMany({
          data: orderItems,
        });

        // Empty the user's cart
        await prisma.cartItem.deleteMany({
          where: {
            cart: {
              userId: userId,
            },
          },
        });

        await prisma.cart.update({
          where: { id: cart.id },
          data: {},
        });
        revalidatePath("/", "layout");
      });
    } catch (error) {
      console.error("Error handling checkout session:", error);
    }
  }

  return new NextResponse("ok", { status: 200 });
}

and here is what is printed out when I console.log the whole session.

{
  id: *the id is here*,
  object: 'charge',
  amount: 1499,
  amount_captured: 1499,
  amount_refunded: 0,
  application: null,
  application_fee: null,
  application_fee_amount: null,
  balance_transaction: null,
  billing_details: {
    address: {
      city: 'Austin',
      country: 'US',
      line1: '3186 Brentwood Drive',
      line2: null,
      postal_code: '78746',
      state: 'TX'
    },
    email: '[email protected]',
    name: 'John Doe',
    phone: null
  },
  calculated_statement_descriptor: 'JOHN DOE',
  captured: true,
  created: 1722718453,
  currency: 'usd',
  customer: null,
  description: null,
  destination: null,
  dispute: null,
  disputed: false,
  failure_balance_transaction: null,
  failure_code: null,
  failure_message: null,
  fraud_details: {},
  invoice: null,
  livemode: false,
  metadata: {},
  on_behalf_of: null,
  order: null,
  outcome: {
    network_status: 'approved_by_network',
    reason: null,
    risk_level: 'normal',
    risk_score: 35,
    seller_message: 'Payment complete.',
    type: 'authorized'
  },
  paid: true,
  payment_intent: 'pi_3PjoxtRu5CVeMm6U0PoyXjnC',
  payment_method: 'pm_1PjoxsRu5CVeMm6UvlsVXLbb',
  payment_method_details: {
    card: {
      amount_authorized: 1499,
      authorization_code: null,
      brand: 'visa',
      checks: [Object],
      country: 'US',
      exp_month: 11,
      exp_year: 2042,
      extended_authorization: [Object],
      fingerprint: '08eKoYQiOE8pTlLD',
      funding: 'credit',
      incremental_authorization: [Object],
      installments: null,
      last4: '4242',
      mandate: null,
      multicapture: [Object],
      network: 'visa',
      network_token: [Object],
      overcapture: [Object],
      three_d_secure: null,
      wallet: null
    },
    type: 'card'
  },
  radar_options: {},
  receipt_email: null,
  receipt_number: null,
  receipt_url: 'https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xUGZDT1pSdTVDVmVNbTZVKPaxurUGMgYiOLShtJk6LBZH4IQkJ4DUUBK9TzBeAOdnf8adJI3SNgJhlihMuQHs9e8IDacRGL5vePD12-',
  refunded: false,
  review: null,
  shipping: {
    address: {
      city: 'AUSTIN',
      country: 'US',
      line1: '3186 Brentwood Drive',
      line2: null,
      postal_code: '78746',
      state: 'TX'
    },
    carrier: null,
    name: 'John Doe',
    phone: null,
    tracking_number: null
  },
  source: null,
  source_transfer: null,
  statement_descriptor: null,
  statement_descriptor_suffix: null,
  status: 'succeeded',
  transfer_data: null,
  transfer_group: null
}

and when I check an individual item such as

console.log(session.shipping_details?.address?.state);

it just prints out undefined, which is weird.

ALSO, you may have noticed, and I find it really weird too, but when I am trying to access the information in session, and try to do a session.”autocomplete” to get the available keys to choose from, it does not give me just basic shipping. only shipping_details, which is really weird as well. I can seem to access top level keys, such as session.created, but deeper keys value pairs don’t seem to work. I have never dealt with this before so I am very confused.

I have console.logged about every possible way I can think about. I have looked through the documentation, but it mostly just shows me how the session object is structured, but nothing that might make me understand why it is not working.

Headers Error while making discord authorization page (javascript)

Im making a website with dashboard for a discord bot. Only when im making the authorization page with the help of JWT to make a token it keeps giving me a headers error (see below). Ill put my code for that specific item under here. Can someone please help me out because I can’t seem to find any source of why said error pops up.


Error:

node:_http_outgoing:703
    throw new ERR_HTTP_HEADERS_SENT('set');
          ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (node:_http_outgoing:703:11)
    at ServerResponse.header (C:xampphtdocsdiscordapiapinode_modulesexpresslibresponse.js:795:10)
    at ServerResponse.send (C:xampphtdocsdiscordapiapinode_modulesexpresslibresponse.js:175:12)
    at ServerResponse.json (C:xampphtdocsdiscordapiapinode_modulesexpresslibresponse.js:279:15)
    at C:xampphtdocsdiscordapiapisrcroutesauthindex.js:109:32
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

Node.js v21.6.0
Failed running '.'

Code:

const express = require('express');
const User = require('../../models/User');
const jwt = require('jsonwebtoken');

const router = express.Router();

// GET: designy.xyz/auth/signin
// GET: designy.xyz/auth/callback

const DASHBOARD_URL = 'http://localhost:5173';

router.get('/signin', (req, res) => {
    res.redirect(
        `https://discord.com/oauth2/authorize?client_id=${process.env.DISCORD_CLIENT_ID}&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fauth%2Fcallback&scope=guilds+identify`
    );
});

router.get('/callback', async (req, res) => {
    const DISCORD_ENDPOINT = 'https://discord.com/api/v10';
    const CLIENT_ID = process.env.DISCORD_CLIENT_ID;
    const CLIENT_SECRET = process.env.DISCORD_CLIENT_SECRET;
    const REDIRECT_URI = process.env.DISCORD_REDIRECT_URI;
    const DASHBOARD_URL = process.env.DASHBOARD_URL;

    const { code } = req.query;

    if (!code) {
        return res.status(400).json({
            error: 'A "code" query parameter must be present in the URL.',
        });
    }

    try {
        const oauthRes = await fetch(`${DISCORD_ENDPOINT}/oauth2/token`, {
            method: 'POST',
            body: new URLSearchParams({
                client_id: CLIENT_ID,
                client_secret: CLIENT_SECRET,
                grant_type: 'authorization_code',
                redirect_uri: REDIRECT_URI,
                code,
            }).toString(),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        });

        if (!oauthRes.ok) {
            return res.status(500).json({
                error: 'Failed to obtain OAuth token.',
            });
        }

        const oauthResJson = await oauthRes.json();

        const userRes = await fetch(`${DISCORD_ENDPOINT}/users/@me`, {
            method: 'GET',
            headers: {
                Authorization: `Bearer ${oauthResJson.access_token}`,
            },
        });

        if (!userRes.ok) {
            return res.status(500).json({
                error: 'Failed to fetch user data.',
            });
        }

        const userResJson = await userRes.json();

        let user = await User.findOne({ id: userResJson.id });

        if (!user) {
            user = new User({
                id: userResJson.id,
                username: userResJson.username,
                avatarHash: userResJson.avatar,
                accessToken: oauthResJson.access_token,
                refreshToken: oauthResJson.refresh_token,
            });
        } else {
            user.username = userResJson.username;
            user.avatarHash = userResJson.avatar;
            user.accessToken = oauthResJson.access_token;
            user.refreshToken = oauthResJson.refresh_token;
        }

        await user.save();

        const token = jwt.sign(
            {
                id: userResJson.id,
                username: userResJson.username,
                avatarHash: userResJson.avatar,
            },
            process.env.JWT_SECRET,
            { expiresIn: '7d' }
        );

        res.cookie('access_token', token, {
            httpOnly: true,
            secure: process.env.NODE_ENV === 'production',
            maxAge: 6.048e8,
        });

        return res.redirect(DASHBOARD_URL);
    } catch (error) {
        console.error(error);
        return res.status(500).json({
            error: 'Internal Server Error.',
        });
    }
});

router.get('/signout', (req, res) => {
    res.clearCookie('token').sendStatus(200);
});

module.exports = router;

Help would be much appreciated!

Ive tried to remove the .send .json. status to see if that would fix the issue.

Ive also tried to remove the res.redirect + token to see if that would’ve helped

Both of these things did not work, also tried some other things but i can’t remember them anymore.