Navigation Bar isn’t Responsive in Phone View

I have a navigation bar that isn’t responsive. I would like for it to change into a 3 bar menu you click on when the website is being viewed from a phone but it doesn’t seem to be working. Here’s a gif of what I am talking about.

enter image description here

As you can see the nav bar at the top is completely disappearing when resized. Would really appreciate it if someone could explain where I’ve gone wrong please.

Heres the code

const mainMenu = document.querySelector('.mainMenu');
const closeMenu = document.querySelector('.closeMenu');
const openMenu = document.querySelector('.openMenu');




openMenu.addEventListener('click',show);
closeMenu.addEventListener('click',close);

function show(){
    mainMenu.style.display = 'flex';
    mainMenu.style.top = '0';
}
function close(){
    mainMenu.style.top = '-100%';
}
nav {
    color: white;
    display: flex;
    justify-content: space-between;

}

nav .mainMenu {
    display: flex;
    list-style: none;
        font-family: "SR";
}

nav .mainMenu li a {
    display: inline-block;
    padding: 15px;
    text-decoration: none;
    text-transform: uppercase;
    color: white;
    font-size:  1.5vw;
}

nav ul li a:hover {
    color: white;
    z-index: 10000;
      font-family: "SR";
}

nav ul ul {
    position: absolute;
    top: 40px;
    display: none;
    z-index: 10000;
left: 0%;
}

nav ul li:hover > ul {
    display: block;
    z-index: 10000;
    animation: none;
}



nav ul ul li {
    width: 100%;
    float: none;
    display: list-item;
    position: relative;
    z-index: 10000;
      white-space: nowrap;
}

nav ul ul ul li {
    position: relative;
    margin-top: -60px;
    left: 100%;
    z-index: 10000;
    white-space: nowrap;
}

a.active {
    opacity: 1;
}

 ul li a:nth-of-type(1) {
     
     opacity: 0.5;
   

}

 ul li a.active:nth-of-type(1) {
   color: #fff;
   opacity: 1;

   cursor: url(Cursors/3.png), auto;

}
 ul li a:hover:nth-of-type(1) {
    color: #fff;
    opacity: 1;
 
    position: sticky;
    border: none;
    box-shadow: none;
    transition-delay: 0s;

 
    cursor: url(Cursors/3.png), auto;
}

 a:nth-of-type(2) {
z-index: 10000;

}


nav ul li {
    background: transparent;
    position: relative;
    list-style: none;
    display: inline-block;
    z-index: 10000;
  font-family: "SU";

}

nav .openMenu {
    font-size: 1.9vw;
    margin: 20px;
    display: none;
    cursor: pointer;
}

nav .mainMenu .closeMenu, .icons i {
    font-size: 1.9vw;
    display: none;
    cursor: pointer;
}

nav .logo {

    font-size: 1.7vw;
    cursor: pointer;
      letter-spacing: 0.2rem;
      margin-left: 2%;
      margin-top: 0.8%;
      padding-top: 10px;
}

.mainMenu {

    margin-top: 1%;
}
@media only screen and (max-width: 414px)  {


    nav .mainMenu {
        height: 100vh;
        position: fixed;
        top: 0;
        right: 0;
        left: 0;
        z-index: 10000;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        background: black;
        transition: top 1s ease;
        display: none;
    
    }


   

    nav .mainMenu .closeMenu {
        display: block;
        position: absolute;
        top: 20px;
        right: 20px;
    }



    nav .openMenu {
        display: block;
    }

    i {
        display: inline-block;
        padding: 12px;
        
        margin-top: -40%;
        left: ;
    }



.closeMenu {
    position: absolute;
    margin-top: -538px;
    left: 131px;
}

 nav .logo {
    margin: 6px;
    font-size: 3.8vw;
    cursor: pointer;
      letter-spacing: 0.2rem;
      margin-left: 4%;
      margin-top: 0.5%;

}

nav a {
    font-size: 3vw;
}


nav .mainMenu li a {
    display: inline-block;
    padding: 15px;
    text-decoration: none;
    text-transform: uppercase;
    color: white;
    font-size:  5vw;
}

nav ul ul ul li {
    position: relative;
    margin-top: -60px;
    left: 150%;
    z-index: 10000;

   }
   nav ul ul li {
    width: 100%;
    float: none;
    display: list-item;
    position: relative;
    z-index: 10000;
    white-space: normal;
    margin-left: 90%;
    margin-top: -30%;
  
}
.masonry .mItem {
  display: inline-block;
  margin-bottom: 4px;
  width: 98%;
  z-index: -1;
}

img {
    z-index: 10000;
}
}
<nav>
        <div class="logo"><h2>GALLERY</h2></div>
        <div class="openMenu"><i class="fa fa-bars fa-3x" ></i></div>
        <ul class="mainMenu">
        <li><a href="#" class="active">Gallery</a></li>
                <li><a href="https://ayanfesanusi.com/">Home</a></li>
                <li><a href="https://ayanfesanusi.com/About/index.html">About</a></li>
                <li class="hasDD"><a href="https://ayanfesanusi.com/About/Projects/index.html">Projects</a></li>
                <li><a href="https://ayanfesanusi.com/About/Contact/index.html">  Contact</a><li>
                <div class="closeMenu"><i class="fa fa-times fa-4x"></i></div>
        </ul>           
    </nav>

How to include spaces in a text content?

I want to ask how to make my paragraph look exactly the same as how i write my text in a textarea?

I want to make it look like the following:

enter image description here

But currently it’s displayed like this

enter image description here

I’m using a javascript.

I’ve tried to do this but apparently it doesn’t work

  
document.addEventListener("keydown", function(event, statusParagraph){
  if (event.key === "Enter") {
    // Insert a line break into the content
    statusParagraph.innerHTML += "<br>";
  }
});

Property ‘layout’ does not exist on type ‘FC’. in Next.js

I am getting above error in my _app.tsx file . I am trying to use multiple layout which is normally working but typescript is giving error

here are the code

import Layout from '@/components/layouts'
import NoLayout from '@/components/layouts/NoLayout'
import '@/styles/globals.css'
import { Nunito } from 'next/font/google'
import type { AppProps } from 'next/app'
import { CompProps, WrapperProps } from '@/lib/utils'


const layouts: Record<string, React.FC<WrapperProps>> = {
  L1: Layout,
  L2: NoLayout,
};

interface CustomAppProps extends AppProps {
  Component: React.FC<CompProps>;
}

export default function App({ Component, pageProps }: CustomAppProps) {
  const SelectedLayout = layouts[Component.layout || 'L1'] || (({ children }) => <>{children}</>);

  return (
    <div className={nunito.className}>
      <SelectedLayout>
        <Component {...pageProps} otherProps={Component.otherProps} />
      </SelectedLayout>
    </div>
  );
}

and this is my utils.ts file

export type CompProps = {
  footer?: boolean;
  style?: string;
  layout?: string;
}

export interface WrapperProps {
  children: React.ReactNode;
  otherProps?: CompProps;
}

but in my _app.tsx i am getting this typescript error

Property 'layout' does not exist on type 'FC<WrapperProps>'.
Property 'otherProps' does not exist on type 'FC<WrapperProps>'.

Code is working fine but typeScript is the issue
i am not getting why i am unable to resolve this error, Also I am new to TypeScript please guide me

How to hide a key in react js app (for frontend React and backend salesforce )

I am using a react app for frontend and salesforce for backend so I want to hide an API key so it should not be visible to user so what should I do ?

I got some solution like .env variables but if I commit the changes then how code will work as the key is in my machine only so I want a method to hide in such a way that user does not have to do something extra just only download the package so is there any method in salesforce or react hide an api key.

What should be the correct pull request process? [closed]

I am not sure this is the best place to ask code review code question, if not, please point me to the right place.

I have a question about story, code, pull request in general.

Other devs raise pull requests. Many of times are bandaid fix. After it is merged, it is a bit hard to maintain and the code flow is not fluent. (imagine that 10 of these bandaid fixes merged into the code base, it is getting harder and harder to maintain)

I asked them to fix the pr. Response is that it is a new requirement, need to create a new story. Or it is not part of the story, do it later. Or we don’t have time, let’s merge it 1st.

If code flow is in quality, it will be much easier to maintain large code base.

What should be the correct pull request process? Am I doing wrong?

In Typescript, My exported Javascript type is neither a function or a constructor

I’m new to Typescript and Javascript I got to admit. I have a repo now initialized with NextJS and I am trying to import a third party *.js to my project as a component in such way I could import it from my other typescript files.

The one I used is MSABrowser.

What I have tried:

I have made small personal changes on that script so probably I cannot import as a released package. Anyway, I put this msabrowser.js file under components/msabrowser/ and import it using ES6 grammar like

import { MSABrowser, MSAProcessor } from "@/components/msabroswer/msabrowser"

And also, I made a msabrowser.d.ts file under the same folder, writter like this to export both MSABroswer and MSAProcessor

interface MSAProcessor {
  (options: { fasta: string; hasConsensus?: boolean }): MSAProcessor;

  sequenceDetails: any[];
  processedSequences: string[];
  fasta: string;
}
declare const MSAProcessor: MSAProcessor;
export = MSAProcessor;

export class MSABrowser {
  constructor(options: {
    id: string;
    msa: MSAProcessor;
    annotations?: any[];
    alterations?: any[];
  });
}

I use the following code to import and use MSABrowser and MSAProcessor:

viewer = new MSABrowser({
  id: "myMSABrowser",
  msa: new MSAProcessor({
    fasta: content,
    hasConsensus: false,
  }),
  annotations: annotations,
  alterations: alterations,
});

However my Chrome keeps complaining me:
_components_msabrowser_msabrowser__WEBPACK_IMPORTED_MODULE_2__.MSAProcessor is not a constructor. Well If I remove new keyword to treat it as a function. It would say: TypeError: (0 , _components_msabrowser_msabrowser__WEBPACK_IMPORTED_MODULE_2__.MSAProcessor) is not a function

Doesn’t know if this help, but in my tsconfig, my target and module are all set to esnext

Any suggestions? Thanks in advance.

Is it possible to enable in browser settings ‘On startup – Continue where you left off’ with Playwright/Puppeter on javascript?

I need to open a browser and switch to the current page (e.g. stackoverflow.com) then close the browser and open it again with this saved page (e.g. stackoverflow.com). I know that in the browser settings you can make it so that when you open it you can start from where you closed the browser. That is, all tabs will be saved when opened. Is it possible to do this with Puppeteer?

Y tried looking for flags, cannot find anything useful, and y really could like a solution that does not rely on saving all open tabs then opening again

React: Button not Displaying or Changing Color in CountryCapitalGame [duplicate]

I am trying to solve a react problem. I followed the below youtube tutorial.I am trying in code sandbox.
For some reason I am not seeing the button and change in color. Can you let me know how to fix it. Providing my code snippet below.
I debugged but still no luck

https://codesandbox.io/p/sandbox/state-zw845m?file=%2Fsrc%2FApp.tsx%3A9%2C1-37%2C2

https://www.youtube.com/watch?v=XTgB4esy1is&t=1335s

function CountryCapitalGame({ data }: { data: Record<string, string> }) {
    const countries = Object.keys(data);
    const capitals = Object.values(data);
    // let us combine into arrays
    const options = [...countries, ...capitals];
    const [colorMap, setColorMap] = useState<Record<string, ButtonState>>({});
    const [options, setOptions] = useState<Option[]>(
        [...countries, ...capitals].map((value) => ({
            value,
            state: "DEFAULT"
        }))
    );

    options.sort((a, b) => Math.random() - 0.5);
    return (
        <>
            {options.map((option) => (
                <button
                    className={colorMap[option] === "SELECTED" ? "selected" : ""}
                    onClick={() => {
                        setColorMap({ ...colorMap, [option]: "SELECTED" });
                    }}
                >
                    {option}
                </button>
            ))}
        </>
    );
}

In p5.js I am trying to run two music tracks, one of the music tracks keeps on creating an error of undefined when doing .play() command

This is a small snippet of the game I’m coding. The code that does not work is MenuMusic.play(); once I remove this line everything runs
perfectly.

I have tried to replace the MenuMusic.play(); with the one that does work, BackgroundMusic.play();,but it still gives the error of undefined, so its not a problem with the music needing replacing. I have also tried separating both parts of the code but that did nothing to help.

//Variables
var Menu = 0; // 0 = main menu, 1 = level select, 2 = level 1, 3 = you died, 4 = level complete, 5 = credits
var PlayedMenuMusic = false; //false has not played, true has played
var PlayedBackgroundMusic = false; //false has not played, true has played


function setup() {
  MenuMusic = loadSound("centaur-forest-60695.mp3");
  BackgroundMusic = loadSound("8bit-music-for-game-68698.mp3");
}

function draw() {
  if (
    (Menu == 2 || Menu == 5) &&
    BackgroundMusic.isPlaying() == false &&
    PlayedBackgroundMusic == false
  ) {
    //Background Music
    BackgroundMusic.play();
    PlayedBackgroundMusic = true;
    //Menu Music
    MenuMusic.stop();
    PlayedMenuMusic = false;
  }
  if (
    (Menu == 0 || Menu == 1 || Menu == 3 || Menu == 4) &&
    MenuMusic.isPlaying() == false &&
    PlayedMenuMusic == false
  ) {
    //Meny Music
    MenuMusic.play();
    PlayedMenuMusic = true;
    //Background Music
    BackgroundMusic.stop();
    PlayedBackgroundMusic = false;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/addons/p5.sound.min.js"></script>

Strange error with importing framer-motion

I am getting the error:

/node_modules/framer-motion/dist/es/components/AnimatePresence/index.mjs
Can’t import the named export ‘Children’ from non EcmaScript module (only default export is available)

I am quite frustrated that this error is persisting, and I have tried many different solutions, including running ‘npm i -S framer-motion’, and also manually inputting into my package.json as such:

"framer-motion": "^4.1.17", 

and then running npm install. However, that still did not work. The same errors persisted for when I tried to install react-spring. I am using React version 18.2.0, if that helps. As a beginner this is very intimidating that I can’t even install animations into my project.. it is becoming honestly ridiculous so I want to know if anyone at all has a fix.

understand the mechanism of a website so that I can scrape [duplicate]

I want to scrap data from this website using requests and selenium packages of python. However, I do not understand how the data are loaded for this website, so I hope someone can explain its mechanism to me.

In the entire process, the url remains the same. The first time the page is loaded, we are shown an introduction page looking as below.
enter image description here
Then, we need to click the Next button on the topright corner, which will leads us to the parameter selection page below.
enter image description here
On this page, we are allowed to select up to 2 parameters, then we have to click Next again to get to the data page below.
enter image description here

Although I have tried to inspect interactions between my browser and the server through the developer tool, I could not figure out how the data were loaded, so I hope someone can explain the mechanism to me. Besides, in my scraping script, is it possible to set more than two parameters?

React-navigation crashes expo apk

i made an expo project that has installed react-navigation/ and react-navigation/native-stack, and when the apk file generated is installed and the app is opened, it automatically crashes and closes with no message. These are the files that i have:

App.js:

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import { HomeScreen, ProfileScreen } from './Home';

const Stack = createNativeStackNavigator();

export default App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{title: 'Welcome'}}
        />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

Home.js:

import { Button, Text } from "react-native";

export const HomeScreen = ({ navigation }) => {
    return (
        <Button
            title="Go to Jane's profile"
            onPress={() =>
                navigation.navigate('Profile', { name: 'Jane' })
            }
        />
    );
};
export const ProfileScreen = ({ navigation, route }) => {
    return <Text>This is {route.params.name}'s profile</Text>;
};

package.json:

{
  "name": "testtt",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@react-navigation/native": "^6.1.9",
    "@react-navigation/native-stack": "^6.9.16",
    "expo": "~49.0.15",
    "expo-status-bar": "~1.6.0",
    "react": "18.2.0",
    "react-native": "0.72.6"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true
}

I tried to install it in other phones but the app still crashing. Thanks a lot

localstorage is not defined next.js [duplicate]

I’m trying to blockade user access to the admin path, but I’m getting localstorage is not defined next.js error in next.js. How can I fix this?

const getUserRole = () => {
const user = JSON.parse(localStorage.getItem("user"));
return user ? user.role : null;

};

Need to change particles color when mouse move by THREE JS

I have a particle image that made from shader texture and i need the color that gl_FragColor.rgb = texture.rgb; animate to change color like a weather forecast map or rotate color change.

my scene.js

import {
  Color,
  WebGLRenderer,
  Scene,
  PerspectiveCamera,
  AxesHelper,
  BufferGeometry,
  BufferAttribute,
  Points,
  ShaderMaterial,
  Raycaster,
  Vector2,
  Vector3,
} from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import Stats from 'stats-js'
import LoaderManager from '@/js/managers/LoaderManager'
import GUI from 'lil-gui'

import vertexShader from '@/js/glsl/main.vert'
import fragmentShader from '@/js/glsl/main.frag'
import { randFloat } from 'three/src/math/MathUtils'
import gsap from 'gsap'
import TouchTexture from './TouchTexture'
import { isTouch } from '@/js/utils/isTouch'

export default class MainScene {
  canvas
  renderer
  scene
  camera
  controls
  stats
  width
  height
  customMaterial

  constructor() {
    this.canvas = document.querySelector('.scene')

    this.touch = new TouchTexture()

    this.init()
  }

  init = async () => {
    const assets = [
      {
        name: 'background',
        texture: './img/image.jpg',
      },
    ]

    await LoaderManager.load(assets)

    this.setStats()
    this.setScene()
    this.setRender()
    this.setCamera()
    // this.setControls()
    this.setParticlesGrid()
    this.setRaycaster()

    this.handleResize()

    this.events()

    this.animateIn()
  }

  setRender() {
    this.renderer = new WebGLRenderer({
      canvas: this.canvas,
      antialias: true,
    })
  }

  setScene() {
    this.scene = new Scene()
  }

  setCamera() {
    const aspectRatio = this.width / this.height
    const fieldOfView = 60
    const nearPlane = 0.1
    const farPlane = 10000

    this.camera = new PerspectiveCamera(fieldOfView, aspectRatio, nearPlane, farPlane)
    this.camera.position.y = 0
    this.camera.position.x = 0
    this.camera.position.z = 250
    this.camera.lookAt(0, 0, 0)

    this.scene.add(this.camera)
  }


  setControls() {
    // this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    // this.controls.enableDamping = true
  }

  setParticlesGrid() {
    const geometry = new BufferGeometry()

    const particles = []
    const initPositions = []
    const multiplier = 18
    const nbColumns = 16 * multiplier
    const nbLines = 9 * multiplier

    this.nbColumns = nbColumns
    this.nbLines = nbLines

    const halfColumn = nbColumns / 2
    const halfLines = nbLines / 2


    for (let i = 0; i < nbLines; i++) {
      for (let y = 0; y < nbColumns; y++) {
        const point = [i, y, 0.0]

        let initPoint = [i - halfLines, y - halfColumn, randFloat(100, 500)]

        particles.push(...point)
        initPositions.push(...initPoint)
      }
    }

    const vertices = new Float32Array(particles)
    const initPositionsFloat = new Float32Array(initPositions)

    geometry.setAttribute('position', new BufferAttribute(vertices, 3))
    geometry.setAttribute('initPosition', new BufferAttribute(initPositionsFloat, 3))

    geometry.center()

    this.dpr = 2
    this.uniforms = {
      uColor: { value: new Color(0xffffff) },
      uPointSize: { value: 1.5 },
      uTexture: { value: LoaderManager.assets['background'].texture },      
      uNbLines: { value: nbLines },
      uNbColumns: { value: nbColumns },
      uProgress: { value: 0 },
      uTime: { value: 0 },
      uTouch: { value: this.touch.texture },
      uScaleHeightPointSize: { value: (this.dpr * this.height) / 2 },
      uMouse: { value: new Vector2(0, 0) },
      uColorChange: { value: new Vector3() },

    }

    this.customMaterial = new ShaderMaterial({
      uniforms: this.uniforms,
      vertexShader,
      fragmentShader,
      transparent: true,
      depthTest: false,
      depthWrite: false,
    })
    this.mesh = new Points(geometry, this.customMaterial)

    this.scene.add(this.mesh)
  }

  animateIn() {
    gsap.fromTo(
      this.uniforms.uProgress,
      {
        value: 0,
      },
      {
        value: 1,
        duration: 2.5,
        ease: 'Power4.easeOut',
      }
    )
  }

  setAxesHelper() {
    const axesHelper = new AxesHelper(3)
    this.scene.add(axesHelper)
  }


  setStats() {
    this.stats = new Stats()
    this.stats.showPanel(0)
    document.body.appendChild(this.stats.dom)
  }

  events() {
    window.addEventListener('resize', this.handleResize, { passive: true })
    this.draw(0)

  }

  draw = (time) => {
    this.stats.begin()

    if (this.controls) this.controls.update()
    this.uniforms.uTime.value += 0.05;

    this.renderer.render(this.scene, this.camera)

    this.touch.update()

    this.stats.end()
    this.raf = window.requestAnimationFrame(this.draw)
  }

  handleResize = () => {
    this.width = window.innerWidth
    this.height = window.innerHeight

    this.camera.aspect = this.width / this.height
    this.camera.updateProjectionMatrix()

    this.renderer.setPixelRatio(this.dpr)
    this.renderer.setSize(this.width, this.height)

    this.uniforms.uScaleHeightPointSize.value = (this.dpr * this.height) / 2
  }

  setRaycaster() {
    this.ray = new Raycaster()
    this.mouse = new Vector2()

    if (isTouch()) {
      window.addEventListener('touchmove', this.handleTouchMove)
    } else {
      window.addEventListener('mousemove', this.handleMouseMove)
    }
  }

  handleMouseMove = (e) => {
    const x = (e.clientX / window.innerWidth) * 2 - 1
    const y = -(e.clientY / window.innerHeight) * 2 + 1
    this.mouse.x = x
    this.mouse.y = y

    this.ray.setFromCamera(this.mouse, this.camera)
    this.intersects = this.ray.intersectObjects([this.mesh])

    if (this.intersects.length) {
      const uv = new Vector2(0.5, 0.5)
      uv.x = this.intersects[0].point.x / this.nbLines + 0.5
      uv.y = this.intersects[0].point.y / this.nbColumns + 0.5
      this.touch.addTouch(uv)

      const colorChange = new Vector3(x, y, 1.0);
      this.uniforms.uColorChange.value = colorChange;
      this.uniforms.uMouse.value = new Vector2(x, y);
    }


  }

  handleTouchMove = (e) => {
    const x = (e.touches[0].clientX / window.innerWidth) * 2 - 1
    const y = -(e.touches[0].clientY / window.innerHeight) * 2 + 1

    this.mouse.x = x
    this.mouse.y = y

    this.ray.setFromCamera(this.mouse, this.camera)
    this.intersects = this.ray.intersectObjects([this.mesh])

    if (this.intersects.length) {
      const uv = new Vector2(0.5, 0.5)
      uv.x = this.intersects[0].point.x / this.nbLines + 0.5
      uv.y = this.intersects[0].point.y / this.nbColumns + 0.5
      this.touch.addTouch(uv)

      const colorChange = new Vector3(x, y, 1.0);
      this.uniforms.uColorChange.value = colorChange;
    }
  }


}

fragment shader

precision highp float;

uniform vec3 uColor;
uniform sampler2D uTexture;
uniform float uNbLines;
uniform float uNbColumns;
uniform float uProgress;
uniform float uScroll;
uniform vec3 colorChange;
uniform vec2 uMouse;
uniform vec3 uColorChange;
uniform sampler2D uTouch;

varying vec2 vTexCoords;


float circle(vec2 uv, float border) {
    float radius = 0.5;
    float dist = radius - distance(uv, vec2(0.5));
  return smoothstep(0.0, border, dist);
}

void main() {

  vec2 uv = gl_PointCoord;
  
  uv.y *= -1.;
  uv /= vec2(uNbLines, uNbColumns);
  
  float texOffsetU = vTexCoords.x / uNbLines;
  float texOffsetV = vTexCoords.y / uNbColumns;
  uv += vec2(texOffsetU, texOffsetV);
  uv += vec2(0.5);

  vec4 texture = texture2D(uTexture, uv);

  gl_FragColor.rgb = texture.rgb;

  if(gl_FragColor.r < 0.1) {
    discard;
  }

  gl_FragColor.a = 1.;
  gl_FragColor.a *= circle(gl_PointCoord, 0.2);
  gl_FragColor.a *= uProgress;
}

vertex shader

precision highp float;

uniform float uPointSize;
uniform float uProgress;
uniform sampler2D uTouch;
uniform float uTime;
uniform float uNbLines;
uniform float uNbColumns;
uniform float uScaleHeightPointSize;
attribute vec3 initPosition;
uniform vec2 uMouse;


varying vec2 vTexCoords;

const float scale = 1.0;

float random(vec2 st) {
    return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}

void main() {
    #include <begin_vertex>

    vec2 mouseOffset = uMouse - vec2(0.5, 0.5);
    vec3 offset = vec3(mouseOffset, 0.0);


    transformed = initPosition + ((position - initPosition) * uProgress);
    vec2 direction = transformed.xy - uMouse;

    vec2 vUv = transformed.xy / vec2(uNbLines, uNbColumns) - vec2(-0.5, -0.5);

    float touch = texture2D(uTouch, vUv).r;

    // transformed.xy += direction * touch * 0.2;

    #include <project_vertex>

    vTexCoords = position.xy;

    gl_PointSize = uPointSize * ( uScaleHeightPointSize / - mvPosition.z );
}

Discord.js collecting button interaction for buttons attached to replies

I have a Discord.js bot that lets users vote on the outcome of games. Users can vote for team1 or team2 by clicking one of the buttons that the /addGame slash command generates. Once you have voted for a winner, I’d like the users to be able to then vote for how many games it will take by clicking a button that is attached to the bot reply for which team they voted for:

enter image description here

Right now the error shown is the only one I’m getting. No errors in the console. This is the entire slash command function:

/addGame.js

imports...

const collectorMap = new Map();

// Function to create series buttons
function createSeriesButtons(series) {
    const buttons = [];

    for (let i = 2; i <= series; i++) {
        buttons.push(new ButtonBuilder()
            .setCustomId(`button${i}`)
            .setStyle(ButtonStyle.Secondary)
            .setEmoji(`${i}️⃣`)
        );
    }

    return buttons;
}


module.exports = {
    data: new SlashCommandBuilder()
        .setName('addgame')
        .setDescription('Sets up a game for placing bets.')
        .addStringOption(option =>
            option.setName('team1')
                .setDescription('Team 1')
                .setRequired(true)
                .addChoices(
                    ...teams
                ))
        .addStringOption(option =>
            option.setName('team2')
                .setDescription('Team 2')
                .setRequired(true)
                .addChoices(
                   ...teams
                ))
        .addStringOption(option =>
            option.setName('series')
                .setDescription('Number of games')
                .setRequired(true)
                .addChoices(
                    { name: '1', value: '1'},
                    { name: '3', value: '3'},
                    { name: '5', value: '5'},
                )),
    async execute(interaction) {
        // Set up team information
        const teamList = await getTeams();
        const team1 = interaction.options.getString('team1');
        const team2 = interaction.options.getString('team2');
        const teamArray = [team1, team2];
        let teamMessage1 = '';
        let teamMessage2 = '';
        const team1Info = teamList.find(team => team.Name === teamArray[0]);
        const team2Info = teamList.find(team => team.Name === teamArray[1]);
        teamMessage1 = team1Info.Emoji + ' ' + team1Info.Name;
        teamMessage2 = team2Info.Name + ' ' + team2Info.Emoji;

        const series = interaction.options.getString('series');

        // Build buttons
        const team1Button = new ButtonBuilder()
            .setCustomId('team1Button')
            .setStyle(ButtonStyle.Secondary)
            .setEmoji(team1Info.Emoji);

        const team2Button = new ButtonBuilder()
            .setCustomId('team2Button')
            .setStyle(ButtonStyle.Secondary)
            .setEmoji(team2Info.Emoji);

        const row = new ActionRowBuilder()
        .addComponents(team1Button, team2Button);

         const message2 = await client.channels.cache.get('1162487828417085650').send({
             content: teamMessage1 + ' vs ' + teamMessage2,
             components: [row],
         });

         await addGame(team1, team2, series, message2.id);

         // Send the message and add buttons
         await interaction.reply({content: 'Game posted.' + team1Info.Emoji + ' ' + team2Info.Emoji + ' : ' + message2.id, fetchReply: true});

         const collector = message2.createMessageComponentCollector({ componentType: ComponentType.Button, time: 172800000 });

         collectorMap.set(message2.id, collector);



         collector.on('collect', async i => {
            // Get the collector associated with the message using message ID
            const messageCollector = collectorMap.get(i.message.id);

            try {
        
                if (i.customId === 'team1Button' || i.customId === 'team2Button') {

                    const seriesButtons = createSeriesButtons(parseInt(series));
                    const seriesRow = new ActionRowBuilder().addComponents(...seriesButtons);
                    const team = await getTeamEmoji(i.message.id, i.customId);
    
                    await castVote(team.name, i.user.username, i.message.id).then(() => {
                        i.reply({ 
                            content: "Vote for " + team.emoji + " submitted.", 
                            components: [seriesRow],
                            ephemeral: true });
                    });

                } else if (i.customId.startsWith('button')) {
                    console.log('We got here');
                    // Handle series vote when series buttons are clicked
                    const seriesLength = i.customId.replace('button', ''); // Extract the series length from the customId
                    console.log(seriesLength);
                    try {
                        await seriesVote(seriesLength, i.user.username, i.message.id).then(() => {
                            i.reply({ 
                                content: `Vote for ${seriesLength} games submitted.`, 
                                ephemeral: true });
                        });
                    } catch (error) {
                        console.error("Error submitting series vote:", error);
                        logError(error, i.message.id, i.user.username, 'Error submitting series vote');
                    }
                }

        } catch (error) {
            console.error("Button interaction error:", error);
            console.log("Interaction Object:", i);
            console.log("Button interaction user: ", i.user.username);
            console.log("Button interaction messageID: ", i.message.id);
            logError(error, i.message.id, i.user.username, 'Button interaction error: ' + i);
        }
        });
    },
};

However I believe where we are focused is right here:

collector.on('collect', async i => {
            // Get the collector associated with the message using message ID
            const messageCollector = collectorMap.get(i.message.id);

            try {
        
                if (i.customId === 'team1Button' || i.customId === 'team2Button') {

                    const seriesButtons = createSeriesButtons(parseInt(series));
                    const seriesRow = new ActionRowBuilder().addComponents(...seriesButtons);
                    const team = await getTeamEmoji(i.message.id, i.customId);
    
                    await castVote(team.name, i.user.username, i.message.id).then(() => {
                        i.reply({ 
                            content: "Vote for " + team.emoji + " submitted.", 
                            components: [seriesRow],
                            ephemeral: true });
                    });

                } else if (i.customId.startsWith('button')) {
                    console.log('We got here');
                    // Handle series vote when series buttons are clicked
                    const seriesLength = i.customId.replace('button', ''); // Extract the series length from the customId
                    console.log(seriesLength);
                    try {
                        await seriesVote(seriesLength, i.user.username, i.message.id).then(() => {
                            i.reply({ 
                                content: `Vote for ${seriesLength} games submitted.`, 
                                ephemeral: true });
                        });
                    } catch (error) {
                        console.error("Error submitting series vote:", error);
                        logError(error, i.message.id, i.user.username, 'Error submitting series vote');
                    }
                }

        }
    ...

I think the problem may be with the collector? It’s like the bot doesn’t understand how to collect button interactions from buttons that are attached to replies. However, the bot doesn’t have a problem collecting multiple votes for different games if you add several at a time using /addGame.

Any advice greatly appreciated.