Javascript Calculator Sqrt root button error?

I’ve been trying to build a calculator to understand javascript better as a n00b, but I can’t figure out why I have this error.

I type 64 on the calculator, then it types 648, instead of 8.

What I’d like it to do… is be able to type in √(68) in the calculator and then it displays 8…

so say, √(16)+2 = 6. ^^;; As supposed to √(16+2)= 4.24264068

but I’m not quite sure if I’m asking for too much and it wasn’t clear from puttering around how one would do this.

I’m thinking more like the TI calculator type of function, instead of the scientific calculator function.

BTW, I’m aware that the rest of it barely functions…


    else if (value == "√") {
        value = Math.sqrt(display.value);
        }

Live version with the bugs: https://kimyoonmi.com/calculator/

calculator.php


    <!DOCTYPE html>
    <html>
    <head>
        <title>Calculator</title>
        <link rel="stylesheet" href="calculator.css">
        </head>
        <body>
    <p>
    
    <div id="calccontainer">
        <div id="calculator">
                <input type=text id="display">
                <div id="buttons"></div>
        </div>
    </div>
            <script src="calculator.js"></script>
        </body>
    </html>

.css


    body { 
        margin:0;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
    }
    
    #calccontainer{
        background-color: lightyellow;
        border-radius: 10px;
    }
    
    #calculator {
        font-family: Arial, sans-serif;
        background color: yellow;
        border-radius: 15px;
        max-width: 800px;
        overflow: hidden;
        border-collapse: separate;
    }
    
    
    #display {
        background-color: white;
        color: black;
        text-align: left;
        font-size: 50px;
        border-width: 1px;
        border-color: gold;
        border-radius: 15px;
        outline: none;
        width: 100%;
        box-sizing: border-box;
    }
    
    #buttons{
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        gap: 5px;
        padding 5px;
    }
    
    #buttons button{
        width: 100px;
        height: 100px:
        border: 0;
        border-radius: 20px;
        background-color: gold;
        color: white;
        font-size: 3rem;
        font-weight: bold;
        cursor: pointer;
        border-collapse: separate; 
    }

const display = document.getElementById("display");

const buttonValues = [
    "Rad", "º", "x!", "(", ")", "%", "AC",
    "Inv", "sin", "log", "7", "8", "9", "÷",
    "π", "cos", "ln", "4", "5", "6",  "x",
    "e", "tan", "√", "1", "2", "3",  "+",
    "Ans", "EXP", "xʸ", "0", ".", "=", "-", "+/-", "x⁻¹",

]

const leftSymbols = ["Rad", "º", "x!", "Inv", "sin", "log", "π", "cos", "ln", "e", "tan", "√", "Ans", "EXP", "xʸ", "+/-", "x⁻¹",]
const topSymbols = ["(", ")", "%", "AC"]
const rightSymbols = [ "÷", "x", "-", "+", "="]


//A+B, A×B, A-B, A÷B
let A = 0;
let operator = null;
let B = null;

function clearAll() {
    A = null;
    operator = null;
    B = null;
}



for (let i = 0; i < buttonValues.length; i++) {
    let value = buttonValues[i];
    let button = document.createElement("button");
    button.innerText = value;
    
    //styling button colors
    
 if (value == "=") {
        button.style.backgroundColor = "brown";
    }
    
    
    else if (rightSymbols.includes(value)) {
        button.style.backgroundColor = "orange";
    }
    
    else if (leftSymbols.includes(value)) {        
        button.style.backgroundColor = "darkorange";
        button.style.color = "white";
    }
    
    else if (topSymbols.includes(value)) {        
        button.style.backgroundColor = "orange";
        button.style.color = "white";
    }
   //process button clicks
    button.addEventListener("click", function() {
        if (leftSymbols.includes(value)) { 
        if (value == "x!") {
    
            }
        else if (value == "√") {
            value = Math.sqrt(display.value);
            }
            
        else if (value == "π") {
                value = 3.141592653589;
            }
            
        }

        else if (rightSymbols.includes(value)) { //÷,=,-,+
            
            }
             if (value == "=") {
                if (A != null) {
                    B = display.value;
                    let numA = Number(A);
                    let numB = Number(B);

                    if (operator == "÷") {
                        display.value = numA/numB;

                    }
                    else if (operator == "×") {
                        display.value = numA*numB;

                    }
                    else if (operator == "-") {
                        display.value = numA-numB;

                    }
                    else if (operator == "+") {
                        display.value = numA+numB;
                    }
                 clearAll();
                }

        }
                else if (topSymbols.includes(value)) { //AC +/- %
            if (value == "AC") {
                clearAll();
                display.value = "";
            }
              else if (value == "+/-") {
                  if (display.value != "" && display.value != "0") {
                    if (display.value[0] == "-") { //remove -
                        display.value = display.value.slice(1); 
                    } else { //add -
                        display.value = "-" + display.value; 
                    }
                }
            }
        else if (value == "%") {
                display.value = Number(display.value) / 100;
            }
            
         else if (value == "(") {
                display.value = "(" + Number(display.value);
            }
            
        else if (value == ")") {
                display.value = (display.value) + ")";
            }
            

        }
        
        else { //digits or .
            if (value == ".") {
                //don't add multiple decimal places
                if (display.value != "" && !display.value.includes(value)) {
                    display.value += value;
                }
            }
            //not a dot, number instead
            else if (display.value == "0") {
                display.value = value;
            }
            else {
                display.value += value;
            }
        }
    });
    
   
    //add button to calculator
    document.getElementById("buttons").appendChild(button);
}

Next.js 15 – How to Render Separate Desktop and Mobile Components with Different Data Without Double Rendering/Fetching?

I’m working on a project using Next.js 15 with server components. I have a page that needs two very different versions: one for desktop and another for mobile. Because the UI is drastically different between the two, I created two entirely separate components — one for mobile and one for desktop — each with its own layout and data requirements.

To handle responsiveness, I conditionally show/hide these components using CSS based on breakpoints (e.g., setting display: none).

However, this approach causes a few problems:

  • Both components are always rendered on the server, even if one is
    hidden.

  • This leads to unnecessary data fetching, especially from the desktop
    version while I’m on a mobile device.

  • Since these are server components, I can’t conditionally render them
    based on window.innerWidth or media queries from the client side.

Is there a recommended pattern in Next.js 15 to conditionally render different server components based on the user’s device (e.g., mobile vs desktop), in a way that avoids rendering and fetching data for both?

How to remove line-breaks from javascript text file?

I’m trying to remove line breaks (enter) from a javascript text file, but when I do the web page doesn’t read it properly anymore… I can remove tabs and carriage returns and the file works just fine, but as soon as I remove the new line characters it all breaks… I’m getting undefined variables and all sorts, even though the variables are still there, defined and initialized inside the file, with the ; character after them, they’re just all on the same line now.

does javascript need the line breaks to work? Here’s my code:

for (char c : content) {
    if (c != 't' && c != 'n' && c != 'r') {
        output += c;
    }
}

React-native web bundling failed

I have this message on my terminal (windows) when i start an expo server :

Web Bundling failed 151ms index.js (41 modules)
Unable to resolve “react-native-web/dist/exports/StyleSheet” from “App.js”

anyone with a solution??

js sourcemap that maps a to t.a

I am developing a js code converter. here is a(much simplified) example input.js

let a=5
let b=6
const result = a + b;
console.log(result)

and the corresponding output.js

const t={}
t.a=5
t.b=6
t.result = t.a + t.b;
console.log(t.result)

I would like to debug the input.js using chrome devtools. While debugging, I want to run output.js, but see input.js on the devtool debugger. I am using source map for that and it works. the problem is that when hovering on a, I don’t see the corresponding value t.a

my question is: is is possible to create a source map that will show me the value of t.a while hovering on a?

JavaScript Web Speech API – Utterance cut off sometimes

I have a small TypeScript application that uses JavaScript SpeechSynthesis with the following code:

private speakWords(words: string) {
  const utter = new SpeechSynthesisUtterance();
  utter.lang = 'en-US';
  utter.text = words;

  window.speechSynthesis.speak(utter);
}

The problem I run into is that sometimes the first part of the sentence (or word) is simply cut off. Take this simple-demo-workout-webapp as example: https://budisoft.at/silent-workout/workout/warmup
If I click on “Triple Row” repeatedly it sometimes correctly speaks “Triple Row”. Sometimes it will just swallow part of the first word, sometimes even the entire word.

I tried different variants, including cancelling previous Utterances, delaying the call for 100ms, etc – nothing changes this behavior.

This does not happen an all devices. On my mobile phone for example it works fine. Though on the Windows 11 PC I currently debug the problem on it is completely reproducable (happens about 50% of the time) with Edge, Chrome and Firefox equally.

Any ideas?

Firebase – Cannot Read Property Undefined persistent issue (React Native)

I’ve been facing this issue with my React Native project which i’ve tried bringing back to life after a while.

I’ve tried numerous solutions but have not come to any fix.

The issue started with

TypeError: _compat.default.auth is not a function (it is undefined)

After making some changes to my config file, im getting different forms of the same error such as

TypeError: Cannot read property ‘firestore’ of undefined, js engine: hermes

I’ve attached my package.json and firebase config file below for anyone who may know of a permanent fix.

firebase/config.tsx

import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import "firebase/compat/firestore";
import "firebase/compat/storage";

// Firebase config object
const firebaseConfig = {
  apiKey: "xxxxxxxxxxxxxxxx",
  authDomain: "xxxxxxxxxxxxxxxx",
  projectId: "xxxxxxxxxxxxxxxx",
  storageBucket: "bxxxxxxxxxxxxxxxx",
  messagingSenderId: "2078619xxxx",
  appId: "1:207xxxxxx:web:b869828e04bfxxxxxxxx",
  measurementId: "G-9RZQxxxxxx"
};


if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
}

const firestore = firebase.firestore();
if (firestore && firestore.settings) {
  firestore.settings({ experimentalAutoDetectLongPolling: true });
}

//const analytics = getAnalytics(app);
const db = firebase.firestore();
const auth = firebase.auth()
const storageRef = firebase.storage().ref();

export { db, auth, storageRef, firebase }

package.json

{
    "name": "myproject",
    "version": "1.0.0",
    "scripts": {
        "start": "expo start --dev-client",
        "android": "expo run:android",
        "ios": "expo run:ios",
        "web": "expo start --web",
        "eject": "expo eject"
    },
    "dependencies": {
        "@expo-google-fonts/raleway": "^0.2.3",
        "@freakycoder/react-native-bounceable": ">=1.0.3",
        "@gorhom/bottom-sheet": "^4",
        "@react-native-community/checkbox": "^0.5.15",
        "@react-native-firebase/app": "^18.2.0",
        "@react-native-firebase/auth": "^17.5.0",
        "@react-navigation/material-top-tabs": "^6.6.3",
        "@react-navigation/native": "^6.1.6",
        "@react-navigation/native-stack": "^6.9.12",
        "@react-navigation/stack": "^6.3.16",
        "@rneui/base": "^0.0.0-edge.2",
        "@rneui/themed": "^0.0.0-edge.2",
        "dayjs": "^1.11.13",
        "expo": "^53.0.0",
        "expo-app-loading": "~2.1.1",
        "expo-blur": "~14.1.5",
        "expo-haptics": "~14.1.4",
        "expo-image-picker": "~16.1.4",
        "expo-location": "~18.1.5",
        "expo-splash-screen": "~0.30.9",
        "expo-status-bar": "~2.2.3",
        "expo-updates": "~0.28.15",
        "firebase": "^9.22.0",
        "geolib": "^3.3.3",
        "lottie-react-native": "7.2.2",
        "react": "19.0.0",
        "react-dom": "19.0.0",
        "react-native": "0.79.4",
        "react-native-animatable": "^1.3.3",
        "react-native-bouncy-checkbox": "^3.0.7",
        "react-native-floating-label-input": "^1.4.2",
        "react-native-gesture-handler": "~2.24.0",
        "react-native-google-places-autocomplete": "^2.5.1",
        "react-native-image-header-scroll-view": "^0.10.3",
        "react-native-keyboard-aware-scroll-view": "^0.9.5",
        "react-native-maps": "1.20.1",
        "react-native-nested-scroll-view": "^9.0.0",
        "react-native-pager-view": "6.7.1",
        "react-native-reanimated": "~3.17.4",
        "react-native-root-toast": "^3.6.0",
        "react-native-safe-area-context": "5.4.0",
        "react-native-safe-area-view": "^1.1.1",
        "react-native-screens": "~4.11.1",
        "react-native-shared-element": "^0.8.8",
        "react-native-svg": "15.11.2",
        "react-native-swiper": "^1.6.0",
        "react-native-tab-view": "^3.5.2",
        "react-native-vector-icons": "^9.2.0",
        "react-native-web": "^0.20.0",
        "react-simple-form-validator": "^0.3.1",
        "valtio": "^1.10.5"
    },
    "devDependencies": {
        "@babel/core": "^7.24.0",
        "@types/react": "~19.0.10",
        "@types/react-native": "~0.72.0",
        "@types/react-native-vector-icons": "^6.4.13",
        "typescript": "~5.8.3"
    },
    "private": true
}

Oracle APEX Hide/Show No Data Found Message

I have a requirement to hide the No Data Found message on an Interactive Report when page is initially loaded then show back the message if there is no data.

I have search items (Say PX_Search_Item_1, PX_Search_Item_2) on the region and a button Search and underneath an Interactive Report based on the search items. Initially we need to hide the No Data Found message but when Search button clicks, there is no data then show back the No Data Found or any custom message.

Would it be possible? Your help and support would be appreciated.

Nuxt/ VueJS change color of SVGs in img tags using currentColor not working [duplicate]

Why doesn’t currentColor work when importing SVGs using an img tag in VueJS? I’ve done it this way a million times before but for some reason it isn’t working when using an img tag and setting fill="currentColor", does anyone know what I need to change?

Does vue/nuxt require I import the svg in a different way? I don’t want to have it inline on the page ideally.

I’ve tried setting color with normal classes, tailwind classes, and even inline styles right in the element (not in the svg but in the img and in the container of the img and in the container of the container hahaha)

I’ve also tried setting fill even though I know that currentColor works with color.

SVG (This is one of my smaller ones, but the problem occurs with all svgs):

<svg width="800px" height="800px" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="currentColor">

<g>

<path d="M22.3,8.4c-0.8,0-1.4,0.6-1.4,1.4c0,0.8,0.6,1.4,1.4,1.4c0.8,0,1.4-0.6,1.4-1.4C23.7,9,23.1,8.4,22.3,8.4z"/>

<path d="M16,10.2c-3.3,0-5.9,2.7-5.9,5.9s2.7,5.9,5.9,5.9s5.9-2.7,5.9-5.9S19.3,10.2,16,10.2z M16,19.9c-2.1,0-3.8-1.7-3.8-3.8   c0-2.1,1.7-3.8,3.8-3.8c2.1,0,3.8,1.7,3.8,3.8C19.8,18.2,18.1,19.9,16,19.9z"/>

<path d="M20.8,4h-9.5C7.2,4,4,7.2,4,11.2v9.5c0,4,3.2,7.2,7.2,7.2h9.5c4,0,7.2-3.2,7.2-7.2v-9.5C28,7.2,24.8,4,20.8,4z M25.7,20.8   c0,2.7-2.2,5-5,5h-9.5c-2.7,0-5-2.2-5-5v-9.5c0-2.7,2.2-5,5-5h9.5c2.7,0,5,2.2,5,5V20.8z"/>

</g>

</svg>

vue.js:

<div class="socials text-white">
 <NuxtLink to="https://www.instagram.com/blahblah" class="text-white">
    <img src="/images/icons/insta.svg" alt="Instagram" class="text-white"/>
 </NuxtLink>
</div>

css

  .socials {
    color: var(--white);
    fill: var(--white);
    a {
      color: var(--white);
      fill: var(--white);
    }
    img {
      color: var(--white);
      fill: var(--white);
    }
  }

I have no fills or colors set anywhere in the SVGs, I have tried setting all the css styles and the tailwind styles to important and nothing does anything other than putting the color directly into a fill tag in the .svg file!!! why?!

Upload file contents to Notion

I’m trying to adapt the “Upload file” part into a Google Apps Script. I’ve managed to do the first part (creating the pending file)

Script to adapt (Notion documentation):

// Open a read stream for the file
const fileStream = fs.createReadStream(filePath)

// Create form data with the (named) file contents under the `file` key.
const form = new FormData()
form.append('file', fileStream, {
    filename: path.basename(filePath)
})

// HTTP POST to the Send File Upload API.
const response = await fetch(
    `https://api.notion.com/v1/file_uploads/${fileUploadId}/send`,
    {
        method: 'POST',
        body: form,
        headers: {
            'Authorization': `Bearer ${notionToken}`,
            'Notion-Version': notionVersion,
        }
    }
)

// Rescue validation errors. Possible HTTP 400 cases include:
// - content length greater than the 20MB limit
// - FileUpload not in the `pending` status (e.g. `expired`)
// - invalid or unsupported file content type
if (!response.ok) {
    const errorBody = await response.text()
    console.log('Error response body:', errorBody)
    throw new Error(`HTTP error with status: ${response.status}`)
}

const data = await response.json()
// ...

But I’m really struggling with how to replace the FormData structure…
Here is one of my attempts, which show this error :

Exception: Request failed for https://api.notion.com returned code 400

function uploadFileContentx(uploadUrl, file) {
  var service = getService();
  if (service.hasAccess()) {

    const imgb64data = file.getBlob().getBytes();

    var form = {
            date : new Date(),
            subject : "Picture joined",
            comment : "xxxxxxxxxxxxx",
            attachment1 : `data:image/png;base64,${imgb64data}`,
          };

    var options = {
      method: 'POST',
      muteHttpExceptions : false,
      headers: {
        'Notion-Version': API_VERSION,
        Authorization: 'Bearer ' + service.getAccessToken(),
        contentType: 'multipart/form-data'
      },
      body: {
        'file' : `data:image/png;base64,${imgb64data}`
      }
    };
    Logger.log(JSON.stringify(options, null, 2));

    var response = UrlFetchApp.fetch(uploadUrl, options);

    if (!response.ok) {
      const errorBody = response.text
      console.log('Error response body:', errorBody)
      throw new Error(`HTTP error with status: ${response.status}`)
    }

    return response.getResponseCode() === 200;

  } else {
    var authorizationUrl = service.getAuthorizationUrl();
    Logger.log('Open the following URL and re-run the script: %s',
        authorizationUrl);
  }
}

How do I create a Google Sheets function to get information from a dictionary API?

I have a Google Sheet containing a list of vocab words, and I’m trying to write three functions that will produce the definition, synonyms, and antonyms from the Merriam-Webster API.

In the project editor, I have five scripts – an ImportJSON script and then the four below. When I then go to the Google Sheet and put in =runjs(shortdef) or =runjs(synonyms) or =runjs(antonyms), it says ReferenceError: fetch is not defined (line 4).

Any help would be appreciated!

Javascript:

/**
 * Evaluates JS code.
 *
 * @param {code} code The code to evaluate.
 * @return The result from evaluating the code.
 * @customfunction
 */
function RUNJS(code) {
  return eval(code); 
}

Definitions:

const API_KEY = 'mykeyhere';
const WORD = 'dance';

fetch(`https://www.dictionaryapi.com/api/v3/references/collegiate/json/${WORD}?key=${API_KEY}`)
  .then(response => response.json())
  .then(data => {
    const definition = data[0].shortdef[0];
    console.log(definition);
  })
  .catch(error => console.log(error));

Synonyms:

const API_KEY = 'mykeyhere';
const WORD = 'set';

fetch(`https://www.dictionaryapi.com/api/v3/references/collegiate/json/${WORD}?key=${API_KEY}&synonyms`)
  .then(response => response.json())
  .then(data => {
    const synonyms = data[0].meta.syns[0].join(', ');
    console.log(`Synonyms: ${synonyms}`);
  })
  .catch(error => console.log(error));

Antonyms:

const API_KEY = 'mykeyhere';
const WORD = 'against';

fetch(`https://www.dictionaryapi.com/api/v3/references/collegiate/json/${WORD}?key=${API_KEY}&antonyms`)
  .then(response => response.json())
  .then(data => {
    const antonyms = data[0].meta.ants[0].join(', ');
    console.log(`Antonyms: ${antonyms}`);
  })
  .catch(error => console.log(error));

React header will not display the User Details after Login

Here in my react problem I tried to make a Context in purpose should get the user details after logging in the login page.

It should display the User details in the Header Component

but it will not after I logged in, I don’t know what is wrong.
Here is my Code
UserProvider

    import { useState, createContext, useEffect } from 'react'
    import api from '../api.js'
    import logged from './get_user.js'
    
    
    // eslint-disable-next-line react-refresh/only-export-components
    export const UserContext = createContext()
    
    export function UserProvider({children}){
         const [user, setUser] = useState(null)
    
         const fetchUser = async () => {
              try {
                   const res = api.get('/api/user')
                   const data = res.data
                   setUser(data)
                   console.log('User data: ', data)
              }catch(err){
                   setUser(null)
                   console.log(err)
              }
         }
         console.log(user)
    
         useEffect(()=>{
              if (logged) {
                   fetchUser
              }
         })
         return (
              <>
                   <UserContext.Provider value={{ user, setUser, fetchUser}}>
                        {children}
                   </UserContext.Provider>
              </>
         )
    }

App.jsx

function RegisterAndLogout(){
     localStorage.clear() // Clear the Access Token Before Register
     return <Register />
}
function App() {

     return (
     <>
          <UserProvider>
               <BrowserRouter>
               <HeaderComponent/>
                    ... Some routes
               </BrowserRouter>
          </UserProvider>
     </>
)
}

export default App

Form.jsx For login

    function Form({route, method}) {
         const [username, setUsername ] = useState('')
         const [password, setPassword ] = useState('')
         const [loading, setLoading] = useState(false)
         const { fetchUser } = useContext(UserContext)
    
         const navigate = useNavigate()
         const name = method === 'login' ? "Login" : "Register"
         const handleSubmit = async (e) => {
              // Submission set Loading to True
              setLoading(true)
              e.preventDefault()
    
              try {
                   const res = await api.post(route, {username, password})
                   if (method === 'login') {
                        localStorage.setItem(ACCESS_TOKEN, res.data.access)
                        localStorage.setItem(REFRESH_TOKEN, res.data.refresh)
                        logged(true)
                        await fetchUser
                        navigate('/')
                   } else {
                        navigate('/login')
                   }
              } catch(error) {
                   alert(error)
              } finally {
                   setLoading(false)
              }
    
         }
    return ( SomeJSX and user.username, )

after log in it will pass true
logged function

    export function logged(logged){
         return logged ? true : false
    }

Header Componenent where it should display


    function HeaderComponent(){
         const { user, setUser } = useContext(UserContext)
         console.log(user) nothing will pop out
         const navigate = useNavigate() 
         return ( 
              Some Code 
    )

Do you have a solution for this? Am I doing it wrong?

Additional question how can I clear the token after I close the server?
Is there a way to perform localStorage.clear() or localStorage.remove(‘access’) before closing the server?

Getting undefined result from array query [duplicate]

I’m just beginning my journey with Javascript and have been playing about with a deck of cards.

I have an array set with a standard 52 card deck, and my aim with the code is to display a random card each time, taking the drawn cards out of the array (so they can’t be drawn again, and the deck will eventually run down to 0).

Testing this in the console worked, but now that I’ve put it on to an external JS sheet for a webpage, I’m occasionally getting an error of “undefined” when the random card is being generated.

Any help is gratefully appreciated!

Here’s my Javascript code – there’s no consistency in the error for which card is causing the error, or for number of occurrences – I’ve seen runs with one, two, or three errors, and with different selections each time.

var deck = ['ace_of_clubs', '2_of_clubs', '3_of_clubs', '4_of_clubs', '5_of_clubs', '6_of_clubs', '7_of_clubs', '8_of_clubs', '9_of_clubs', '10_of_clubs', 'jack_of_clubs2', 'queen_of_clubs2', 'king_of_clubs2', 'ace_of_diamonds', '2_of_diamonds', '3_of_diamonds', '4_of_diamonds', '5_of_diamonds', '6_of_diamonds', '7_of_diamonds', '8_of_diamonds', '9_of_diamonds', '10_of_diamonds', 'jack_of_diamonds2', 'queen_of_diamonds2', 'king_of_diamonds2', 'ace_of_hearts', '2_of_hearts', '3_of_hearts', '4_of_hearts', '5_of_hearts', '6_of_hearts', '7_of_hearts', '8_of_hearts', '9_of_hearts', '10_of_hearts', 'jack_of_hearts2', 'queen_of_hearts2', 'king_of_hearts2', 'ace_of_spades', '2_of_spades', '3_of_spades', '4_of_spades', '5_of_spades', '6_of_spades', '7_of_spades', '8_of_spades', '9_of_spades', '10_of_spades', 'jack_of_spades2', 'queen_of_spades2', 'king_of_spades2' ];

function pickACard() {
  if (deck.length > 0) {
    let card = Math.round(Math.random() * deck.length);
    console.log(deck[card]);
    document.querySelector("img").setAttribute("src", "./images/" + (deck[card]) + ".png");
    let remove = deck.indexOf(deck[card]);
    deck.splice(remove, 1);
  } else {
    alert("Please start a new game!")
  }
}
document.getElementById('pick').addEventListener('click',pickACard);
<button type="button" id="pick">Pick</button><br/>
<img src="" alt=""/>

Astro get multple database enteries from diffrent tables and use them on the page

i’am doing a small learning project and was wondering if you guys can help me, async functions are still a bit hard to wrap my head around.
Okey lets begin, For this project i have multple database tabels a Recipe table what hold the instructions, second is the UsedProducts table that keeps note wich product is used in a recipe, and how much its used, and a Products table has all products,
and on the recipe page i want to show the used products but whats the best way to get them from the database?

src/pages/[id]/[name]/[portion].astro

---
import { db, Recipe, eq, RecipeProducts, Product } from "astro:db";

let { id, portion } = Astro.params;

if (!id || !portion) {
    return Astro.redirect("/");
}

// Get the recpie
const recipe = await db.select().from(Recipe).where(eq(Recipe.id, id));

//lookup assosited Products in RecipeProduct Table
const usedProducts = await db
    .select()
    .from(RecipeProducts)
    .where(eq(RecipeProducts.recpieId, id));

let neededProducts = [] as Array<[amount: number, unit: string, name: string]>;

// Get the assosited Products from Product table
usedProducts.forEach(async (p) => {
    console.log(p);
    const product = await db
        .select()
        .from(Product)
        .where(eq(Product.id, p.productId));

    neededProducts.push([p.amount, product[0].id, product[0].name]);
    console.log("Inside " + neededProducts);
});

console.log("Outside " + neededProducts);
---

{recipe[0]?.title}

<h1>Needed products</h1>
<!-- Show products here -->

db/config.ts

import { column, defineDb, defineTable } from "astro:db";

const Recipe = defineTable({
    columns: {
        id: column.text({ primaryKey: true }),
        title: column.text(),
        author: column.text(),
        source: column.text(),
        cover: column.text(),
    },
});

const Product = defineTable({
    columns: {
        id: column.text({ primaryKey: true }),
        name: column.text(),
        measureUnits: column.text(),
    },
});

const RecipeProducts = defineTable({
    columns: {
        id: column.text({ primaryKey: true }),
        recpieId: column.text(),
        productId: column.text(),
        amount: column.number(),
    },
    foreignKeys: [
        {
            columns: ["recpieId"],
            references: () => [Recipe.columns.id],
        },
        {
            columns: ["productId"],
            references: () => [Product.columns.id],
        },
    ],
});

// https://astro.build/db/config
export default defineDb({
    tables: { Recipe, Product, RecipeProducts },
});

The problem doing it this way is that i for some reason cant get the neededProducts array populated ouside the async function, and ofcorse that i make 10+ database querys everythime i load a recipe