Validate Comma Separated String by JOI

I am implementing JOI validation and want to validate comma separated string by JOI. This string contain only particular text string like ‘admin’,’client’, ‘customer’, ‘user’. For example check below. I can validate this by JavaScript, but i want to validate by JOI

function checkString(perm)
{
    const a = ['admin','client', 'customer', 'user'];
     
    const check = perm.split(",");
     
    if(!check.every(val => a.includes(val)))
    {
            return false;
      }
     
      return true;
}
        
//alert(checkString('admin,client,customer'))            //true
//alert(checkString('customer'))                         //true
//alert(checkString('admin,client,buyer'))               //false
//alert(checkString('buyer'))                            //false
//alert(checkString('admin,client,customer,buyer'))      //false

How to transform flat array to a list of hierarchical trees based on a field with a list of enums denoting the level

I’m trying to transform a flat list of account balances to a list of hierarchical account trees based on a list of unique codes. I’m struggling with how to solve this as I can’t see what steps to take.

If you think of an excel sheet then the account balance would be a row and the codes field denotes the columns for how many levels the row has been broken down into. This effectively means that the the first codes[0] is the first level and codes[1] would be the next so on and so forth. By transforming the account balances to an account tree I want to sum the amountOut correctly for each level (codeType and code) and then add it as an account tree in the subAccounts array.

Below I’ve added all the types used as well as provided an example of the input and output.

interface AccountBalance {
    id: string
    codes: Code[]
    amountOut: number
}

type Code = {
    id: string
    codeType: CodeTypes
    code: string
    description: string
}

enum CodeTypes {
    account = "account",
    responsible = "responsible",
    project = "project",
    object = "object",
    counterPart = "counterPart",
    free = "free",
}

type AccountTree = {
    id: string
    name: string
    code: string
    amountOut: number
    subAccounts: AccountTree[]
}

Input example:

const accountBalances: AccountBalance[] = [
            {
                id: "671769fbd36fcd6c2c7f2d9b",
                codes: [
                    {
                        id: "671769fbd36fcd6c2c7f2c2d",
                        codeType: codeTypeEnum.account,
                        code: "1250",
                        description: "Column A",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bd5",
                        codeType: codeTypeEnum.responsible,
                        code: "17",
                        description: "Column B",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bf7",
                        codeType: codeTypeEnum.counterPart,
                        code: "20",
                        description: "Column C",
                    },
                ],
                amountOut: 24510549,
            },
            {
                id: "671769fbd36fcd6c2c7f2d9c",
                codes: [
                    {
                        id: "671769fbd36fcd6c2c7f2c2d",
                        codeType: codeTypeEnum.account,
                        code: "1250",
                        description: "Column A",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bee",
                        codeType: codeTypeEnum.responsible,
                        code: "40",
                        description: "Column B",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2c08",
                        codeType: codeTypeEnum.counterPart,
                        code: "S3",
                        description: "Column C",
                    },
                ],
                amountOut: 0,
            },
            {
                id: "671769fbd36fcd6c2c7f2d9d",
                codes: [
                    {
                        id: "671769fbd36fcd6c2c7f2c2d",
                        codeType: codeTypeEnum.account,
                        code: "1250",
                        description: "Column A",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bdb",
                        codeType: codeTypeEnum.responsible,
                        code: "80",
                        description: "Column B",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bdc",
                        codeType: codeTypeEnum.counterPart,
                        code: "52",
                        description: "Column C",
                    },
                ],
                amountOut: 6381398,
            },
        ]

Output I want, example:

const expected: AccountTree = {
            id: "671769fbd36fcd6c2c7f2c2d",
            name: "Column A",
            code: "1250",
            amountOut: 30891947,
            subAccounts: [
                {
                    id: "671769fbd36fcd6c2c7f2bd5",
                    name: "Column B",
                    code: "17",
                    amountOut: 24510549,
                    subAccounts: [
                        {
                            id: "671769fbd36fcd6c2c7f2bf7",
                            name: "Column C",
                            code: "20",
                            amountOut: 24510549,
                            subAccounts: [],
                        },
                    ],
                },
                {
                    id: "671769fbd36fcd6c2c7f2bee",
                    name: "Column B",
                    code: "40",
                    amountOut: 0,
                    subAccounts: [
                        {
                            id: "671769fbd36fcd6c2c7f2c08",
                            name: "Column C",
                            code: "S3",
                            amountOut: 0,
                            subAccounts: [],
                        },
                    ],

                },
                {
                    id: "671769fbd36fcd6c2c7f2bdb",
                    name: "Column B",
                    code: "80",
                    amountOut: 6381398,
                    subAccounts: [
                        {
                            id: "671769fbd36fcd6c2c7f2bdc",
                            name: "Column C",
                            code: "52",
                            amountOut: 6381398,
                            subAccounts: [],
                        },
                    ],
                },
            ],
        }

What I’ve gotten so far is this

const uniqueCodeTypes = [
        ...new Set(
            accountBalances.reduce<CodeTypes[]>(
                (acc, balance) => [
                    ...acc,
                    ...balance.codes.flatMap((code) => code.codeType),
                ],
                [],
            ),
        ),
    ]

    const uniqueCodesForCodeType = uniqueCodeTypes.map((codeType) => {
        const uniqueCodesForCodeType = [
            ...new Map(
                accountBalances.reduce<Code[]>((acc, balance) => {
                    const code = balance.codes.find(
                        (code) => code.codeType === codeType,
                    )
                    return code ? [...acc, code] : acc
                }, []).map((code) => [code.code, code])
            ).values(),
        ]
        return uniqueCodesForCodeType
    })

But I’m unsure of how to proceed after this.

CORS Issue in my React app (Laravel 10 Backend)

I’m working on a React app with Laravel 10 as the server-side. I’ve configured the cors.php file in Laravel as follows:

'paths' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],  // Allow all origins
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,

When I try to access the audio file via this URL:
http://127.0.0.1:8000/storage/processed_1_1728487168000.mp3

and play it using the following React code:

<audio controls src='http://127.0.0.1:8000/storage/processed_1_1728487168000.mp3'>
  Your browser does not support the audio element.
</audio>

The audio plays perfectly fine.

However, when I set the crossOrigin attribute to “anonymous”, like this:

<audio controls crossOrigin="anonymous" src='http://127.0.0.1:8000/storage/processed_1_1728487168000.mp3'>
  Your browser does not support the audio element.
</audio>

I encounter the following CORS error:

Access to audio at 'http://127.0.0.1:8000/storage/processed_1_1728487168000.mp3' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I’m building an app that visualizes the audio, and when I attempt to visualize it without the crossOrigin attribute, I get the error:
MediaElementAudioSource outputs zeroes due to CORS access restrictions.

I’ve already set 'allowed_origins' => ['*'] in the cors.php file. Is there something I’m missing in my CORS configuration, or is there another solution to resolve this issue?

“How can I stop a timer without using useState and useEffect?”

“In a simple timer component, I want to start and stop it with buttons, but the interval does not stop with a simple clearInterval function. Is there something I am missing?”

import React, { useState } from 'react'

export default function Timer3() {
    const [seconds, setseconds] = useState(0)

    let intervalId;
    const startTimer = () => {
        intervalId = setInterval(() => {
            setseconds((pre) => pre + 1)
        }, 1000)
    }
    const stopTimer = () => {
        clearInterval(intervalId)
    }
    return (
        <>
            {seconds}
            <button onClick={startTimer}>start</button>
            <button onClick={stopTimer}>stop</button>
        </>
    )
}

I know that in the code above, there is a bug: if I press “Start” twice, it will count twice. I am going to fix this after finding out how to make it stop. There is also a solution on the web to use useEffect to run the timer, but I am not looking for code—just a simple answer as to why it does not work.

Rotating 3D object using Javascript (P5JS)

hello and thank you all for taking the time to read this!

I am working for the first time with WEBGL 3D objects within P5JS (javascript). I have four somewhat complicated “separate” 3D objects which, when working as planned, will be manipulated with a mouseOver event. Ideally, when a user moves their mouse over one of the isolated objects, the single object will flip on it’s Y-Axis 180 degrees, and then flip back over when all four have been flipped. I’m having trouble bringing this to life, admittedly due to lack of experience. Hoping someone can point me in the right direction?
There may be some unnecessary or repetitive lines in this code – I apologize. I have been scratching my head over this for many days now and trying many things out to execute my vision, with no luck thus far.

let blueStartR = 144;
let blueStartG = 220;
let blueStartB = 255;

let greenStartR = 147;
let greenStartG = 229;
let greenStartB = 193;

let yelStartR = 249;
let yelStartG = 255;
let yelStartB = 150;

let purpStartR = 200; 
let purpStartG = 240;
let purpStartB = 170;

let swatches = [];

function setup() {
  createCanvas(600, 600, WEBGL);
  //frameRate = 15;
}

function draw() {
  background(195);
  
  //orbitControl();
  
  let swatchOne = new Swatch(-230, purpStartR, purpStartG, purpStartB, 'purple', false);
  swatchOne.id = "purpleSw";
  
  let swatchTwo = new Swatch(-80, blueStartR, blueStartG, blueStartB, 'blue', false);
  swatchTwo.id = "blueSw";
  
  let swatchThree = new Swatch(80, greenStartR, greenStartB, greenStartG, 'green', false);
  swatchThree.id = "greenSw";
  
  let swatchFour = new Swatch(230, yelStartR, yelStartB, yelStartG, 'yellow', false);
  swatchFour.id = "yellowSw";
  
  
  swatches.push(swatchOne);
  swatches.push(swatchTwo);
  swatches.push(swatchThree);
  swatches.push(swatchFour);
  
  for(var i = 0; i < swatches.length; i++){
    drawSwatch(swatches[i]);
    swatches[i].checkOver(mouseX, mouseY);
    //if(swatches[i].over){
    //  
    //}else{
    //  
    //}
  }
}


class Swatch {
  constructor(xTranslate, topColorFinal, topColorSecond, topColorMain, swatchColor, over){
    this.xTranslate = xTranslate;
    this.topColorFinal = topColorFinal;
    this.topColorSecond = topColorSecond;
    this.topColorMain = topColorMain;
    this.swatchColor = swatchColor;
  }
  
  checkOver(mouseX, mouseY){
    if(mouseX > 30 && mouseX < 130 && mouseY > 30 && mouseY < 570){
      //swatches[0].over = true;
      swatches[0].over = true;
      console.log("over purple");
    }
    else{
      swatches[0].over = false;
    }
    if(mouseX > 150 && mouseX < 250 && mouseY > 30 && mouseY < 570){
      swatches[1].over = true;
      console.log("over blue");
    }
    else{
      swatches[1].over = false;
    }
    if(mouseX > 310 && mouseX < 410 && mouseY > 30 && mouseY < 570){
      swatches[2].over = true;
      console.log("over green");
    }
    else{
      swatches[2].over = false;
    }
    if(mouseX > 480 && mouseX < 580 && mouseY > 30 && mouseY < 570){
      swatches[3].over = true;
      console.log("over yellow");
    }
    else{
      swatches[3].over = false;
    }
  }
}

function drawSwatch(SwatchA){
  push();
    noStroke();
    fill('white');
    translate(SwatchA.xTranslate, 0, 0);
    box(100, 550, 2);
  pop();
  
  if(SwatchA.swatchColor == 'blue'){
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorSecond, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, -245, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 50, SwatchA.topColorSecond - 20, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, -175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 100, SwatchA.topColorSecond - 40, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, -105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 150, SwatchA.topColorSecond - 60, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, -35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 200, SwatchA.topColorSecond - 80, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, 35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 250, SwatchA.topColorSecond - 100, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, 105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 300, SwatchA.topColorSecond - 120, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, 175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 350, SwatchA.topColorSecond - 140, SwatchA.topColorMain));
    translate(SwatchA.xTranslate, 245, 1);
    box(101, 60, 2);
  pop();
  }
  
    if(SwatchA.swatchColor == 'green'){
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond));
    translate(SwatchA.xTranslate, -245, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 50, SwatchA.topColorMain, SwatchA.topColorSecond - 20));
    translate(SwatchA.xTranslate, -175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 100, SwatchA.topColorMain, SwatchA.topColorSecond - 40));
    translate(SwatchA.xTranslate, -105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 150, SwatchA.topColorMain, SwatchA.topColorSecond - 60));
    translate(SwatchA.xTranslate, -35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 200, SwatchA.topColorMain, SwatchA.topColorSecond - 80));
    translate(SwatchA.xTranslate, 35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 250, SwatchA.topColorMain, SwatchA.topColorSecond - 100));
    translate(SwatchA.xTranslate, 105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 300, SwatchA.topColorMain, SwatchA.topColorSecond - 120));
    translate(SwatchA.xTranslate, 175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 350, SwatchA.topColorMain, SwatchA.topColorSecond - 140));
    translate(SwatchA.xTranslate, 245, 1);
    box(101, 60, 2);
  pop();
  }
  
      if(SwatchA.swatchColor == 'purple'){
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond));
    translate(SwatchA.xTranslate, -245, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 30, SwatchA.topColorMain - 30, SwatchA.topColorSecond - 30));
    translate(SwatchA.xTranslate, -175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 60, SwatchA.topColorMain - 60, SwatchA.topColorSecond - 60));
    translate(SwatchA.xTranslate, -105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 90, SwatchA.topColorMain - 90, SwatchA.topColorSecond - 90));
    translate(SwatchA.xTranslate, -35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 110, SwatchA.topColorMain - 110, SwatchA.topColorSecond - 110));
    translate(SwatchA.xTranslate, 35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 130, SwatchA.topColorMain - 130, SwatchA.topColorSecond - 130));
    translate(SwatchA.xTranslate, 105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 150, SwatchA.topColorMain - 150, SwatchA.topColorSecond - 150));
    translate(SwatchA.xTranslate, 175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal - 170, SwatchA.topColorMain - 170, SwatchA.topColorSecond - 170));
    translate(SwatchA.xTranslate, 245, 1);
    box(101, 60, 2);
  pop();
  }
  
      if(SwatchA.swatchColor == 'yellow'){
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond));
    translate(SwatchA.xTranslate, -245, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 30));
    translate(SwatchA.xTranslate, -175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 60));
    translate(SwatchA.xTranslate, -105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 90));
    translate(SwatchA.xTranslate, -35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 120));
    translate(SwatchA.xTranslate, 35, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 150));
    translate(SwatchA.xTranslate, 105, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 180));
    translate(SwatchA.xTranslate, 175, 1);
    box(101, 60, 2);
  pop();
  
  push();
    noStroke();
    fill(color(SwatchA.topColorFinal, SwatchA.topColorMain, SwatchA.topColorSecond - 220));
    translate(SwatchA.xTranslate, 245, 1);
    box(101, 60, 2);
  pop();
  }
}

function mouseOver(){
  for(var i = 0; i < swatches[i]; i++){
  //checkOver(mouseX, mouseY);
  }
}

‘Firebase Storage: An unknown error occurred, please check the error payload for server response. (storage/unknown)

I’m making a system to download media from a subfolder inside a main folder with javascript, but it keep showing me an error when I execute the code file, the error it keeps showing me is

)] {
  code: 'storage/unknown',
  customData: { serverResponse: '' },
  status_: 400,
  _baseMessage: 'Firebase Storage: An unknown error occurred, please check the error payload for server response. (storage/unknown)'
}

this shows when I execute the JS file directly.


//THIS IS MY connection.js

// firebaseConfig.js
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore"; // Mantener esta línea para Firestore
import { getStorage, ref, listAll, getDownloadURL } from "firebase/storage"; // Cambiado a 'firebase/storage'

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  databaseURL: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: ""
};

const app = initializeApp(firebaseConfig);
const storage = getStorage(app);

export { app, storage, ref, listAll, getDownloadURL };

//MY download.js

import fs from 'fs';
import path from 'path';
import { pool } from '../postgresconnection.js'; // Conexión a PostgreSQL
import { storage, ref, listAll, getDownloadURL } from '../connection.js'; // Firebase Storage
import axios from 'axios'; // Para realizar la descarga de archivos    

try {
        const storagePath = `${companyName}/${agencyName}`;
        const listRef = ref(storage, storagePath); // Referencia a la carpeta en Firebase
        console.log(`Listando archivos en: ${storagePath}`);

        const res = await listAll(listRef);

        for (const itemRef of res.items) {
            const fileName = itemRef.name;
            try {
                const downloadUrl = await getDownloadURL(itemRef); // Obtener la URL de descarga
                console.log(`URL de descarga para ${fileName}: ${downloadUrl}`);

                const localFilePath = path.join(mediaPath, fileName);
                const writer = fs.createWriteStream(localFilePath);
                const response = await axios({
                    url: downloadUrl,
                    method: 'GET',
                    responseType: 'stream'
                });

                response.data.pipe(writer);

                // Esperar hasta que el archivo esté completamente descargado
                await new Promise((resolve, reject) => {
                    writer.on('finish', resolve);
                    writer.on('error', reject);
                });

                console.log(`Archivo descargado: ${localFilePath}`);
            } catch (downloadError) {
                console.error(`Error al obtener la URL de descarga para ${fileName}:`, downloadError);
            }
        }

        console.log('Descarga completa');
    } catch (error) {
        console.error('Error al buscar y descargar videos:', error);
    }
};

I review my storage in firebase and all the folders exists, i review all the docs i found but none of them shows me like a real solution, I’d used chat GPT for any other answer to that problem but none of the possible solutions worked for me 🙁

Is there a package out there that can add specs to an image?

I’m working on my e-commerce site and i’m adding specs to images currently i’m adding an overlay, that’s displays the line along with the specs.

Is there a package out there that allows you to input the image, width, height, and depth and applies it to an image. something similar to this image.

So far, I’ve been having an overlay image and adding lines along with the measurements but it’s not consistent with all the images and looks very wonky i need something that works well on all images

How do I make a iframe adjust to the height of the content when the content is a PDF?

I have a iframe,but I want to integrate it into the website with no scroll bar, so the size should be the size of the content.

There are many questions about IFrames and making their size equal to their content’s size, but none of the solutions to those questions seem to work in my case.
I tried using
View.js

function resizeIframe(frame) {
    frame.style.height = frame.contentWindow.document.body.scrollHeight + 'px'
}

View.html

        <iframe src="{{source}}" onload="resizeIframe(this)">

        </iframe>

But, all of my content is in PDF files, and frame.contentWindow.document.body.scrollHeight is 0.
How do I do this?

Why is my React component being redirected to Login Component?

I have a react component inside a protected route. When I just render the component without the useEffect, it renders, but when I add the axios request, it redirects me to the login component, even though the user is authenticated and logged in. authenticated state comes back true. I’m not sure why it would redirect to log in if I am authenticated and logged in. When I run the API endpoint in Postman, it returns the user data.

import { useState, useContext, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import axios from "../api/axiosInstance";

import axiosInstance from "../api/axiosInstance";
axios.defaults.withCredentials = true;

export default function Profile() {
  const { profile_id } = useParams();
  const [profile, setProfile] = useState([]);

  const profileUrl = `/profile/${profile_id}`;

  useEffect(() => {
    fetchProfileDetails();
  }, [profile_id]);

  const fetchProfileDetails = async () => {
    try {
      const response = await axiosInstance.get(profileUrl);
      setProfile(response.data);
      console.log(response.data);
    } catch (error) {
      console.log(error);
    }
    
  }

  return (
    <>
    <p>PROFILE PAGE OF {profile}</p>
    </>
  );
}

My Routes:

<Routes>
          <Route path="/" element={<Home />} exact />
          <Route path="/login" element={<Login />} />
          <Route path="/register" element={<Register />} />
          <Route path="/page-not-found" element={<PageNotFound />} />
          <Route element={<ProtectedRoute />}>
            <Route element={<Layout />}>
              <Route path="/feed" element={<Feed />} />
              <Route path="/profile/:profile_id" element={<Profile />} />
              <Route path="/logout" />
            </Route> {/* End of Layout Container */}
          </Route> {/* End of ProtectedRoute container */}
      </Routes>

My ProtectedRoute:

import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { AppContext } from "../Context/AppContext";
import { useContext } from 'react';
import Spinner from './Spinner';

function ProtectedRoute() {
  const location = useLocation();
  const {authenticated} = useContext(AppContext);

  if (authenticated === null) {
    <Spinner />
  }

  return authenticated ? (
    <Outlet />
  ) : (
    <Navigate to="/login" replace state={{ from: location }} />
  );
}

export default ProtectedRoute;

How would i fetch the data from a google apps script web app html form?

Recently I’ve been working with google apps script, google sites, and google sheets hand in hand. My most recent leg of the project has been trying to take input from the google sites website and input into a google sheet using a google apps script webapp. I’ve been doing some research on how to do this and I’ve been told I can fetch the data like i would in normal html however when i do so and output it to the sheet nothing pops up there and since the web app is an detached from the editor i cant view any sort of console log. Any idea how i would be able to make this take the form output and set it to a variable i can then insert into a google sheet?

So far I’ve been able to get my html form created and outputted into the web app so that when executed the form does pop up and once the submit button is pressed the page does load into a new blank one, however there’s no output in the sheet or data in the execution log history. I do see a new cursor in the sheet which confirms the opening and selection of the cell of want but no data what so ever ends up in there. Here is my code so far:

Javascript:

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('register'); 
}

function submitForm(e) {
  var userInputForm = e.document.querySelectorAll('userInput');
  var userInputData = userInputForm.innerHTML;
  console.log(userInputData);
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName(ROSTER);
  var range = sheet.getRange("A3:A3");
  range.setValues(userInputData);
}

HTML:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <form id="myForm">

    <input type="text" id="userInput" placeholder="Enter Username">
    <input type="text" id="discordInput" placeholder="Enter Discord Username">

    <button type="submit">Register</button>

    </form>
  </body>
</html>

OpenAI API TypeError: Configuration or OpenAIApi is not a constructor

// I’ve tried rewriting the code with answers from other stack users and ChatGPT to no avail All packages are up to date oct/24/2024
I expect to programatically interact with OpenAI from my computer terminal. My first request is to hear back.


const { Configuration, OpenAIApi } = require('openai');  // Import the OpenAI classes

// Load the API key from either the environment variable or from the file
const apiKey = process.env.OPENAI_API_KEY || require('./openai_keys');

// Create a Configuration instance with the API key
const configuration = new Configuration({
  apiKey: apiKey,
});

// Instantiate the OpenAIApi with the configuration object
const openai = new OpenAIApi(configuration);

// Create an async function to handle the API request
async function getCompletion() {
  try {
    const completion = await openai.createChatCompletion({
      model: "gpt-4",
      messages: [
        { role: "user", content: "Say, Geronimo!" }
      ],
    });

    console.log(completion.data.choices[0].message.content);  // Print the response
  } catch (error) {
    console.error("Error:", error.response ? error.response.data : error.message);
  }
}

// Call the function to execute the request
getCompletion();

I also rewrote it like this

const { Configuration, OpenAIApi } = require('openai');  // Correct import

const configuration = process.env.OPENAI_API_KEY || require('./openai_keys');


// Instantiate OpenAIApi with the configuration object
const openai = new OpenAIApi(configuration);

TypeError: OpenAIApi is not a constructor

Size of a surface in WebAR

I need to detect a surface (like a wall) and find its size, so I can add some mesh with the size of the detected wall.
Is there any libraries or tools that I can use for finding size of the surface?

Im using threejs library with web-xr for detecting the surface I use hit testing, but I need help with detecting the size

Catapult in matter.js

I’m just starting to learn matter.js in a graphics programming class and we have this optional catapult we can create because we just learned about constraints. The catapult/constraint is not working for me and since I just started learning matter.js I’m really not sure why and would love some help! It’s supposed to be in the middle of the catapult and attached to the world. Thank you!

// Example is based on examples from:
// http://brm.io/matter-js/
// https://github.com/shiffman/p5-matter
// https://github.com/b-g/p5-matter-examples

// module aliases
var Engine = Matter.Engine;
var Render = Matter.Render;
var World = Matter.World;
var Bodies = Matter.Bodies;
var Constraint = Matter.Constraint;

var engine;
var ground;

var ball1;
var ball2;

var catapult;
var catapultSpacer;
var constraint;

function setup() {
  createCanvas(800, 600);
  engine = Engine.create(); // create an engine
  setupCatapult();
  setupBalls();
  setupGround();
}
/////////////////////////////////////////////////////////////
function draw() {
  background(0);
  Engine.update(engine);
  drawBalls();
  drawCatapult();
  drawGround();
}
/////////////////////////////////////////////////////////////
function setupCatapult(){
  // your code here
  catapult = Bodies.rectangle(width/2, height-100, 600, 20, {isStatic: true});
  constraint = Constraint.create({
    pointA: {x: width/2, y: 600},
    bodyB: catapult,
    pointB: {x: 0, y: 0},
    stiffness: 1.0,
    length: 0
  });

  catapultSpacer = Bodies.rectangle(200, height-50, 20, 80, {isStatic: true});
  World.add(engine.world, [catapult, constraint, catapultSpacer]);
}
/////////////////////////////////////////////////////////////
function drawCatapult(){
  // your code here
  fill(255);
  drawVertices(catapult.vertices);
  fill(255, 0, 0);
  drawVertices(catapultSpacer.vertices);
  stroke(255);
  drawConstraint(constraint);
  
}
/////////////////////////////////////////////////////////////
function setupBalls(){
  // your code here
  ball1 = Bodies.circle(550, 30, 60, {density: 0.01, isStatic: false});
  ball2 = Bodies.circle(200, 120, 20);
  World.add(engine.world, [ball1, ball2]);
}
/////////////////////////////////////////////////////////////
function drawBalls(){
  // your code here
  fill(0, 0, 255);
  drawVertices(ball1.vertices);
  drawVertices(ball2.vertices);

}
/////////////////////////////////////////////////////////////
function setupGround(){
  ground = Bodies.rectangle(400, height-10, 810, 25, {isStatic: true});
  World.add(engine.world, [ground]);
}
/////////////////////////////////////////////////////////////
function drawGround(){
  noStroke();
  fill(128);
  drawVertices(ground.vertices);
}
////////////////////////////////////////////////////////////////
// ******* HELPER FUNCTIONS *********
// DO NOT WRITE BELOW HERE
/////////////////////////////////////////////////////////////
function drawVertices(vertices) {
  beginShape();
  for (var i = 0; i < vertices.length; i++) {
    vertex(vertices[i].x, vertices[i].y);
  }
  endShape(CLOSE);
}

function drawConstraint(constraint) {
  var offsetA = constraint.pointA;
  var posA = {x:0, y:0};
  if (constraint.bodyA) {
    posA = constraint.bodyA.position;
  }
  var offsetB = constraint.pointB;
  var posB = {x:0, y:0};
  if (constraint.bodyB) {
    posB = constraint.bodyB.position;
  }
  line(
    posA.x + offsetA.x,
    posA.y + offsetA.y,
    posB.x + offsetB.x,
    posB.y + offsetB.y
  );
}

JavaScript – Array contains HTMLDivElements instead of textContent from the elements (numbers)

I am working on a vanilla JavaScript bingo game. I create my bingo card element, then create a grid. I create 5 arrays of 5 randomized numbers each. Then for each number in each array, I create a div element, add a class of ‘marker’ to the element, stick in the randomized number as the textContent, and append the element to the HTML. Creating the card works fine. I have also set up to mark the spaces on the cards. When a space is marked I add a class of ‘marked’ to it.

Now I am trying to return an array of the marked spaces (this is the first part of a method to check if the person has an actual bingo). I grab all of the card spaces using querySelectorAll(“.marker”). I then run an Array.from filter method to pull out the spaces that contain the ‘marked’ class. Then I assign the textContent (a number) from that space (the div element) to a variable and return that variable. I have a console.log to tell me what the textContent is before I return it. When the filtering is done, I do a console.log of the array that is supposed to contain the values from the textContents of all the elements.

The problem is that instead of showing the numbers from the spaces, the final console log reads as follows:

The marked spaces are: [object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement],[object HTMLDivElement]

The console log inside the filter shows the actual number that is the textContent, and that is what I’m returning in the filter method. So why is the array I’m saving those numbers to showing each as an HTMLDivElement instead of string/number like the inner console log?

Here is my JavaScript code:

const bingoCard = () => {
    const bingoCardSpace = document.getElementById('bingo-card');
    const cardSheet = document.createElement("main");
    cardSheet.classList.add('inline-block', 'mx-auto', 'min-w-fit', 'border-8', 'bg-[#4bb2d3]', 'border-[#4bb2de]');
    bingoCardSpace.appendChild(cardSheet);

    const cardHeader = document.createElement('header');
    cardHeader.classList.add('flex', 'rounded-xl', 'bg-[#345995ff]');
    cardSheet.appendChild(cardHeader);

    const cardLetters = ['B', 'I', 'N', 'G', 'O'];

    for (let i = 0; i < cardLetters.length; i++) {
        const headerCell = document.createElement('div');
        headerCell.textContent = cardLetters[i];
        headerCell.classList.add('w-28', 'h-28', 'font-chewy', 'text-7xl', 'flex', 'justify-center', 'items-center', 'bg-[#f5f5f4ff]','rounded-full', 'mx-2', 'my-2');
        if (i != cardLetters.length - 1) headerCell.classList.add('mr-2');
        cardHeader.appendChild(headerCell);
    }

    const card = document.createElement("div");
    card.setAttribute("id", "card");
    card.classList.add('inline-grid', 'grid-rows-5', 'grid-flow-col', 'bg-[#4bb2de]');
    cardSheet.appendChild(card);

    let cardNumbers = [];
    cardNumbers = createCardArrays();
    for (let i = 0; i < 5; i++) {
        for (let j = 0; j < 5; j++) {
            const cardCell = document.createElement("div");
            let cardCellNumber = cardNumbers[i][j];
            if (i === 2 && j === 2) {
                cardCell.textContent = "FREE";
            } else {
                cardCell.textContent = cardCellNumber;
            }
            cardCell.classList.add('marker', 'w-28', 'h-28', 'font-lato', 'text-5xl', 'flex', 'justify-center', 'items-center', 'bg-[#f5f5f4ff]', 'rounded-full', 'mx-2', 'my-2', cardCellNumber);
            card.appendChild(cardCell);
        }
    }
    listenForMarkingSpaces();
}

function createCardArrays() {
    const cardNumbers = new Array(5);
    let max, min;
    for (let i = 0; i < 5; i++) {
        cardNumbers[i] = [];
        max = 15 * (i + 1);
        min = max - 14;
        cardNumbers[i] = generateRandomNumbers(5, min, max);
    }
    return cardNumbers;
}

function generateRandomNumbers(count, min, max) {
    let uniqueNumbers = new Set();
    while (uniqueNumbers.size < count) {
        uniqueNumbers.add(Math.floor(Math.random() * (max - min + 1)) + min);
    }
    const uniqueNumbersArray = [...uniqueNumbers];
    return uniqueNumbersArray;
}

const bingoBalls = () => {
    const ballArray = [];
    for (let i = 1; i <= 75; i++) {
        ballArray.push(i);
    }
    return ballArray;
}

let bingoBallsNotDrawn = bingoBalls();
let bingoBallsDrawn = [];

const drawBingoBall = () => {
    let ballDrawn = 0;
    while (bingoBallsNotDrawn.indexOf(ballDrawn) === -1) {
        ballDrawn = Math.floor(Math.random() * 75) + 1;
    }
    bingoBallsNotDrawn = bingoBallsNotDrawn.filter(ball => ball !== ballDrawn);
    console.log('bingoBallsNotDrawn now has ' + bingoBallsNotDrawn.length + ' balls in it');
    if (ballDrawn >= 61) ballDrawn = 'O-' + ballDrawn;
    else if (ballDrawn >= 46) ballDrawn = 'G-' + ballDrawn;
    else if (ballDrawn >= 31) ballDrawn = 'N-' + ballDrawn;
    else if (ballDrawn >= 16) ballDrawn = 'I-' + ballDrawn;
    else ballDrawn = 'B-' + ballDrawn;
    bingoBallsDrawn.push(ballDrawn);
    showBallDrawnOnScreen(ballDrawn);
    addBallToBallsDrawnList(ballDrawn);
    console.log('bingoBallsDrawn now has ' + bingoBallsDrawn);
    console.log('bingoBallsNotDrawn: ' + bingoBallsNotDrawn);
}

const showBallDrawnOnScreen = (ballDrawn) => {
    const currentBall = document.getElementById('currentBall');
    currentBall.textContent = "";
    const currentBallNumber = document.createTextNode(ballDrawn);
    currentBall.appendChild(currentBallNumber);
}

const addBallToBallsDrawnList = (ballDrawn) => {
    const ballList = document.getElementById("accordion-content");
    const listedBall = document.createElement("div");
    listedBall.textContent = ballDrawn;
    listedBall.classList.add('text-4xl', 'text-center', 'py-2', 'px-4', 'border-r-2', 'border-l-2', 'border-b-2', 'border-[#714BDE]', 'text-[#714BDE]');
    ballList.appendChild(listedBall);
}

const listenForMarkingSpaces = () => {
    const spaces = document.querySelectorAll(".marker");
    spaces.forEach((space) => {
        space.addEventListener("click", function (evt) {
            space.classList.toggle('bg-[#f5f5f4ff]');
            space.classList.toggle('bg-[#26c485ff]');
            space.classList.toggle('marked');
        });
    });
} 

const toggleAccordion = () => {
    document.getElementById('accordion-content').classList.toggle("hidden");
    document.getElementById('arrow-icon').classList.toggle("rotate-180");
}

const startNewGame = () => {
    const ballList = document.getElementById("accordion-content");
    ballList.innerHTML = '';
    const currentBall = document.getElementById('currentBall');
    currentBall.textContent = '';
    const spaces = document.querySelectorAll(".marker");
    spaces.forEach((space) => {
        space.classList.remove('bg-[#f5f5f4ff]');
        space.classList.remove('bg-[#26c485ff]');
        space.classList.remove('marked');
        space.classList.add('bg-[#f5f5f4ff]');
    });
}

const checkIfMarksAreCorrect = () => {
    const spaces = document.querySelectorAll(".marker");
    const markedSpaces = Array.from(spaces).filter((space) => {
        if (space.classList.contains('marked')) {
            console.log(space.textContent);
            spaceNumber = space.textContent;
            return spaceNumber;
        }
    });
    console.log('The marked spaces are: ' + markedSpaces);
}

And here is my HTML:

<div class="flex">
    <div class="w-3/4 h-100lvh flex flex-col border-r border-black-500" id="bingo-card">
        <div class="flex justify-center">
            <button
                class="rounded-full text-4xl m-4 py-2 px-4 border-2 border-[#714BDE] text-[#714BDE] hover:bg-[#714BDE] hover:text-gray-100 focus:outline-none"
                onclick="startNewGame()">New game</button>
            <button
                class="rounded-full text-4xl m-4 py-2 px-4 border-2 border-[#714BDE] text-[#714BDE] hover:bg-[#714BDE] hover:text-gray-100 focus:outline-none"
                onclick="bingoCard()">Click to create card</button>
            <button
                class="rounded-full text-4xl m-4 py-2 px-4 border-2 border-[#714BDE] text-[#714BDE] hover:bg-[#714BDE] hover:text-gray-100 focus:outline-none"
                onclick="drawBingoBall()">Click to draw ball</button>
            <button
                class="rounded-full text-4xl m-4 py-2 px-4 border-2 border-[#714BDE] text-[#714BDE] hover:bg-[#714BDE] hover:text-gray-100 focus:outline-none"
                onclick="checkIfMarksAreCorrect()">Click to check card</button>
        </div>
    </div>
    <div class="w-1/5">
        <div class="flex mt-4 text-[#714BDE] font-bold justify-center text-4xl">
            Current ball: <span id="currentBall" class="ml-4 text-[#A14BDE]"></span>
        </div>
        <div class="overflow-hidden" onclick="toggleAccordion()">
            <div class="flex text-4xl justify-center mx-4 mt-4 py-2 px-4 border-2 border-[#714BDE] text-[#714BDE]">
                Balls drawn
                <span class="transform transition-transform" id="arrow-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
                        stroke="currentColor" class="size-12">
                        <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
                    </svg>
                </span>
            </div>
            <div class="px-4 hidden" id="accordion-content">

            </div>
        </div>
    </div>
</div>