Custom Stripe checkout embedded – listen for user changes in checkout

Hello everyone 🙂 I hope I can find a good developer who would have time to help develop my problem.

I have a problem with integrating custom embedded stripe checkout for my web application.

The problem is that I want to implement parcel locker logic.
Parcel lockers have their own iframe, so based on the user’s selection in the “shipment” radio buttons, a specific modal should be launched, which will contain an iframe map of this specific supplier.

For example, the user selects “DHL Parcel” from the list of available delivery options. Now I need to somehow get a listener that will respond to me that the user has selected a specific option. This is to trigger my modal, which will allow me to select a parcel locker and after selecting it, enter the value of this parcel locker in the custom field.

I already have the logic that allows me to enter the selected parcel machine into the form fields. The main problem is listening for the user’s change in the scope of delivery. Stripe does not allow delving into the query selector of this iframe checkout so I can’t implement any addEventListner.

Checkout.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <title>Accept a payment</title>
    <meta content="A demo of a payment on Stripe" name="description"/>
    <meta content="width=device-width, initial-scale=1" name="viewport"/>
    <link href="style.css" rel="stylesheet"/>
    <script src="https://js.stripe.com/v3/"></script>
    <script defer src="checkout.js"></script>
</head>
<body>
<div id="checkout">

</div>
</body>
</html>

Server.js:

const stripe = require('stripe')('sk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
const express = require('express');
const app = express();

// Serve static files from the 'public' directory
app.use(express.static('public'));

const YOUR_DOMAIN = 'http://localhost:63342';

app.post('/create-checkout-session', async (req, res) => {
  try {
    const session = await stripe.checkout.sessions.create({
      ui_mode: 'embedded',
      payment_method_types: ['card', 'p24', 'blik'],
      billing_address_collection: 'auto',
      shipping_address_collection: {
        allowed_countries: ['PL'],
      },
      line_items: [
        {
          // Replace '{{PRICE_ID}}' with your actual Price ID
          price: 'price_XXXXXXXXXXX',
          quantity: 1,
        },
        {
          // Replace '{{PRICE_ID}}' with your actual Price ID
          price: 'price_XXXXXXXXXXX',
          quantity: 1,
        },
      ],
      phone_number_collection: {
        enabled: true,
      },
      mode: 'payment',
      return_url: `${YOUR_DOMAIN}/return.html?session_id={CHECKOUT_SESSION_ID}`,
      automatic_tax: { enabled: true },
      custom_fields: [
        {
          key: 'nip',
          label: {
            type: 'custom',
            custom: 'NIP',
          },
          type: 'text',
        },
        {
          key: 'paczkomat',
          label: {
            type: 'custom',
            custom: 'Paczkomat',
          },
          type: 'text',
        },
      ],
      shipping_options: [
        {
          shipping_rate_data: {
            type: 'fixed_amount',
            fixed_amount: {
              amount: 2000,
              currency: 'pln',
            },
            display_name: 'Kurier',
            delivery_estimate: {
              minimum: {
                unit: 'business_day',
                value: 1,
              },
              maximum: {
                unit: 'business_day',
                value: 1,
              },
            },
          },
        },
        {
          shipping_rate_data: {
            type: 'fixed_amount',
            fixed_amount: {
              amount: 2000,
              currency: 'pln',
            },
            display_name: 'Paczkomat InPost',
            delivery_estimate: {
              minimum: {
                unit: 'business_day',
                value: 1,
              },
              maximum: {
                unit: 'business_day',
                value: 1,
              },
            },
          },
        },
        {
          shipping_rate_data: {
            type: 'fixed_amount',
            fixed_amount: {
              amount: 2000,
              currency: 'pln',
            },
            display_name: 'Paczkomat DHL',
            delivery_estimate: {
              minimum: {
                unit: 'business_day',
                value: 1,
              },
              maximum: {
                unit: 'business_day',
                value: 1,
              },
            },
          },
        },
        {
          shipping_rate_data: {
            type: 'fixed_amount',
            fixed_amount: {
              amount: 0,
              currency: 'pln',
            },
            display_name: 'Odbiór osobisty',
            delivery_estimate: {
              minimum: {
                unit: 'business_day',
                value: 1,
              },
              maximum: {
                unit: 'business_day',
                value: 1,
              },
            },
          },
        },
      ],
    });

    // Ensure the clientSecret is being sent correctly
    if (!session.client_secret) {
      throw new Error('Failed to retrieve client secret');
    }

    res.json({ clientSecret: session.client_secret });
  } catch (error) {
    console.error('Error creating checkout session:', error);
    res.status(500).json({ error: error.message });
  }
});


app.get('/session-status', async (req, res) => {
  try {
    const session = await stripe.checkout.sessions.retrieve(req.query.session_id);
    res.send({
      status: session.status,
      customer_email: session.customer_details.email,
    });
  } catch (error) {
    res.status(500).send({error: error.message});
  }
});

app.listen(63342, () => console.log('Running on port 63342'));

Checkout.js:

const stripe = Stripe("pk_live_XXXXXXXXXXXX");

initialize();

// Create a Checkout Session
async function initialize() {
  const fetchClientSecret = async () => {
    try {
      const response = await fetch("/create-checkout-session", {
        method: "POST",
      });

      if (!response.ok) {
        throw new Error('Network response was not ok');
      }

      const data = await response.json();

      if (!data.clientSecret) {
        throw new Error('Client secret not found in the response');
      }

      return data.clientSecret;
    } catch (error) {
      console.error('Error fetching client secret:', error);
      return undefined; // Ensure that an undefined value is not returned, triggering the error
    }
  };

  const checkout = await stripe.initEmbeddedCheckout({
    fetchClientSecret,
  });

  // Mount Checkout
  checkout.mount('#checkout');

  // Nasłuchiwanie na zmiany w metodzie dostawy
  checkout.on('change', (event) => {
    if (event.shippingOption) {
      console.log('Wybrana metoda dostawy:', event.shippingOption);
    }
  });
}

checkout.on(‘change’, (event) not working…

Even if it turns out that I can’t listen for changes in delivery options and do my logic for this, I plan to do multi-step in cart at worst. This means that I will select a delivery option there and possibly a parcel locker from InPost or DHL maps, but then there is another problem, how to pass this information to a custom field called “PARCEL” and immediately set the selected delivery option? The user should no longer be able to change these things (unless they go back to cart) and then click “go to payment” which will again generate a session checkout for me.

I have a lot of ambiguities in my mind, I don’t know how to approach this. I’m implementing Stripe to Webflow, my client has requirements for Polish payment gateways, Webflow doesn’t allow it, I have to use custom checkout. I don’t want to choose another option like Foxy.io or Snipcart.

Matter.js with custom renderer runs twice as fast as it should

I’m trying to use JavaScript to make it so that when certain pieces of text in the document are clicked, they become physical objects and drop down to the bottom of the screen. I’m using matter.js to do this and it’s only the rendering that’s tripping me up.

The default renderer in matter.js doesn’t allow objects to contain text, so I’ve made to cobble one together from what I’ve seen online (without really understanding it). I’m re-rendering each time I add a new object to the scene – which works perfectly fine, apart from the fact that the scene doubles in speed each time it’s rendered!

I’m not a programmer, so apologies for the crazy spaghetti code. I just want this one thing to work and then I’ll never have to look at the matter.js docs again. God, I can’t wait.

const engine = Matter.Engine.create();
const physicscanvas = document.getElementById("physicscanvas"); //canvas the scene is rendered on

const ground = Matter.Bodies.rectangle(
  200, 2560, 2000, 120, {
    isStatic: true
  }
);
Matter.Composite.add(
  engine.world, [ground]
);

(function rerender() {
  Matter.Engine.update(engine);
  requestAnimationFrame(rerender);
})();

//function called whenever text is clicked
function explodeMe(textid) {
  const explodedName = textid.innerHTML;

  //finds x and y of clicked name
  var x_of_physicscanvas = physicscanvas.getBoundingClientRect().left;
  var x_of_text = textid.getBoundingClientRect().left;
  var x_pos_bugged = x_of_text - x_of_physicscanvas;

  var y_of_physicscanvas = physicscanvas.getBoundingClientRect().top;
  var y_of_text = textid.getBoundingClientRect().top;
  var y_pos = y_of_text - y_of_physicscanvas;

  //hide the old text
  textid.style.visibility = "hidden";

  //create the HTML for the falling text
  const fallingContainer = document.createElement("div");
  fallingContainer.innerHTML = explodedName;
  fallingContainer.classList.add("fallingtext");
  physicscanvas.appendChild(fallingContainer);

  //find width + height
  var container_width = fallingContainer.offsetWidth;
  var container_height = fallingContainer.offsetHeight;

  //accounts for skewed width bug
  x_pos = x_pos_bugged + (container_width / 2);

  //convert html into matter.js object
  var box = {
    w: container_width,
    h: container_height,
    body: Matter.Bodies.rectangle(x_pos, y_pos, container_width, container_height, {
      restitution: 0.7
    }),
    elem: fallingContainer,
    render() {
      const {
        x,
        y
      } = this.body.position;
      this.elem.style.top = `${y - this.h / 2}px`;
      this.elem.style.left = `${x - this.w / 2}px`;
      this.elem.style.transform = `rotate(${this.body.angle}rad)`;
    },
  };

  //add matter.js object into canvas
  Matter.Composite.add(
    engine.world, [box.body]
  );

  //render
  (function rerender() {
    box.render();
    Matter.Engine.update(engine);
    requestAnimationFrame(rerender);
  })();

  return;
}
.fallingtext {
  position: absolute;
  z-index: 50;
  color: blue;
  background-color: #0f011f;
  text-align: center;
}

#physicscanvas {
  position: fixed;
  bottom: 0;
  margin: auto;
  width: 800px;
  height: 2500px;
  z-index: -5;
  opacity: 1;
}

html,
body {
  position: relative;
  height: 100%;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script>
<div>
  <div id="physicscanvas">
    <div id="ground"></div>
  </div>
  <p>When <span onclick="explodeMe(this)">this</span> text is clicked, it drops! Likewise, <span onclick="explodeMe(this)">text over here</span> drops too.</p>
</div>

How to remove space between currency symbol and amount in HTML

How to remove the space between Currency Symbol and Amount?

I was trying to remove the space between currency symbol and amount in HTML. But when I am coding it using decimal in HTML, there is a space remaining between currency symbol and amount. Please help me in removing it.
I don’t want this space between INR sign and amount. Here is my current code:-

<span class="discount">&#8377 4500</span> 

React-Native Statusbar not responding to style changes

I have a login/register screen with a video in the background for new user to start the app with in this screen i am popping up modals for either the login or register option. When these modals are up I want to change the status bar from transparent and light text to white background and dark text.

To do that I bound them with a state if the modal is shown or not but it only updates like 1 out of 10 modal pops and I have no idea why.

This is my login screen code:

const LoginScreenMobile = ({ onLogin }) => {
    const [loginModalVisible, setLoginModalVisible] = useState(false)

    return (
        <>
            <StatusBar
                style={loginModalVisible ? 'dark' : 'light'}
            />
            <View style={styles.videoContainer}>
                <LoginModal
                    setVisible={setLoginModalVisible}
                    isVisible={loginModalVisible}
                    modalStyle={styles.modalContainer}
                />
                <Video
                    style={styles.video}
                    source={require('../../assets/videos/login-cooking.mp4')}
                    shouldPlay
                    isLooping
                    isMuted
                    resizeMode="cover"
                />
                <View style={{ flex: 1 }} />
                <View style={styles.textContainer}>
                    <Text style={styles.text}>Food</Text>
                    <Text style={styles.text}>for</Text>
                    <Text style={styles.text}>Family</Text>
                </View>
                <View style={styles.buttonContainer}>
                    <RegisterButton
                        buttonStyle={styles.registerButton}
                        textStyle={styles.registerText}
                    />
                    <LoginButton
                        onLogin={onLogin}
                        buttonStyle={styles.loginButton}
                        textStyle={styles.loginText}
                        setModalVisible={setLoginModalVisible}
                    />
                </View>
            </View>
        </>
    )
}

const styles = StyleSheet.create({
    videoContainer: {
        position: 'absolute',
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
    },
    video: {
        ...StyleSheet.absoluteFillObject,
        zIndex: -1
    },
    modalContainer: {
        flex: 1
    },
}

and this is my modal pop up:

const LoginModal = ({ isVisible, setVisible, modalStyle }) => {

    return (
        <Modal
            visible={isVisible}
            onRequestClose={() => setLoginModalVisible(false)}
            style={[styles.modalContainer, modalStyle]}
            statusBarTranslucent
        >
            <SafeAreaView style={styles.modalOverlay}>
                <View style={styles.modalView}>
                    {/* Close Button */}
                    <TouchableOpacity
                        onPress={() => setVisible(false)}
                        style={styles.closeButton}
                    >
                        <Text style={styles.closeButtonText}>X</Text>
                    </TouchableOpacity>

                    <Text style={styles.modalTitle}>Login</Text>

                    <TextInput
                        placeholder="Email"
                        style={styles.input}
                        keyboardType="email-address"
                        autoCapitalize="none"
                    />
                    <TextInput
                        placeholder="Passwort"
                        style={styles.input}
                        secureTextEntry
                    />

                    <TouchableOpacity
                        onPress={() => setVisible(false)}
                        style={styles.loginButton}
                    >
                        <Text style={styles.buttonText}>Login</Text>
                    </TouchableOpacity>
                </View>
            </SafeAreaView>
        </Modal>
    )
}

I have left out some styling, can provide if needed.

I have basically tried it all by now, putting the status bar in other components, updating it with various other variables and ways, getting rid of the video, isolating the status bar and a button to change it, changing to expo and react-native status bars.
No matter what I do, it doesn’t seem to generate an update 100% of the time.

Thank you!

Access an Object by Variable [duplicate]

I am working on a text adventure. I have a number of rooms, each an object with properties. So… Room_0, Room_1, Room_2, etc. I have a variable CurrLoc which is the room the player is currently in.

How can I access a room OBJECT based on where they are? For instance, if CurrLoc is 2 and I want the room name, I want (“Room_” + CurrLoc).name ….but I can’t figure out how to do that.

Thanks for any help.

I tried console.log((“Room_” + CurrLoc).name) and variations. But I can’t access the Room_2 object itself.

What happens if am using too many frontend component libraries? [closed]

I am using ShadcnUI, AcernityUI, MagicUI, and LukachoUI together in a Vite project with only JavaScript and no TypeScript. My question is, what can go wrong, and what should I take into consideration while working with them?

Often, when I first run the application, everything seems a bit laggy, and some specific components take a lot of time to load. How can I improve this while using components from all the libraries mentioned above?

Next.js API Routes, hide content by session from Nextauth

I need to hide some content on the public API routes, based on the current session.

export const revalidate = 0;
export const dynamic = "force-dynamic";
export const fetchCache = "force-no-store";

export async function GET(request: Request) {
  const session = await getServerSession(config);

  // Example list
  const types = ['item1', 'item2', ....];

  return Response.json(
    {
      // Data from an external API
      data: data.map((item) => {
        if (!session) {
          types.forEach((key: string) => {
            if (item[key]) {
              item[key] = null;
            }
          });
        }

        return item;
      }),
    },
    {
      status: 200,
    },
  );
});

I’m currently using this route.ts, the problem is that when accessing the static generated sites, and it called the URL once, its seem to cache it, and then when logging in, and therefore creating an active session, the route doesn’t update, and still remembers the API data from the call once no session were available.

Anyone know how to fix?
I’m thinking og just creating multiple routes, one for logged in sessions, and one for non-active sessions, but just alot of duplicate work….

there is an full project in JS i can’t do

I am a beginner in this field & i want some help

I tried to do some functions but they didn’t help and watched some YouTube videos and asked for help from chat GPT and black box but it doesn’t work

this project needs to Create the function crosswordSolver that can solve an empty crossword puzzle

How can I trigger hx-post with dynamic url

I’m making a website with HTMX. I usually manage to do what I want with HTMX but I have a problem activating an hx-post with a dynamic URL. I have a list of items that the user must be able to rename and for that I open a modal. When I press the save button of my modal it must activate an hx-post that will send the new name to my API. I need a dynamic URL to have only once the HTML code of my modal without having to hardcode it for each item in the list

Here is the HTML code that I currently have:

<div id="renameModal" class="fixed hidden">
    <div>
        <h2 >Rename Document</h2>
        <form id="renameForm" hx-swap="outerHTML">
            <input type="hidden" id="docIdInput" name="docId" value="">
            <div>
                <label for="nameInput" >New Name</label>
                <input type="text" id="nameInput" name="name" class="required">
            </div>
            <div>
                <button type="button" id="cancelButton" >Cancel</button>
                <button type="submit" >Save</button>
            </div>
        </form>
    </div>
</div>

<script>
    function openRenameModal(docId, docTitle) {
        document.getElementById('renameModal').classList.remove('hidden');
        document.getElementById('docIdInput').value = docId;
        // #title-docId is the id of the p-tag that need to be replace by the api response
        document.getElementById('renameForm').setAttribute('hx-target', '#title-' + docId);
        document.getElementById('renameForm').setAttribute('hx-post', '/document/rename/' + docId);
        document.getElementById('nameInput').value = docTitle;
    }

    document.getElementById('cancelButton').addEventListener('click', function() {
        document.getElementById('renameModal').classList.add('hidden');
    });

    document.getElementById('renameForm').addEventListener('htmx:afterSwap', function(event) {
        if (event.detail.xhr.status === 200) {
            document.getElementById('renameModal').classList.add('hidden');
        }
    });
</script>

When I press “Save” my modal disappears and I am redirected to <url of my site>/<an ID>?docId=<id of the doc a want to rename>&name=<the new name> while I do not want to be redirected, I just want to make a post request to my api and have the document renamed for the client by what the api returns.

How can I make my site work the way I want it to?

AJAX calls based on dropdown selection

I need to fetch the data for a drop down control from the server. Then I need to fetch more data based on what I select in the drop down.

Could somebody explain it by using AJAX, something like this:

$(document).ready(function() {
  $('#journalDropdown').change(function () {
    var journalId = $(this).val();
    if (journalId) {
      $.getJSON('/Order/GetProducts', { journalId: journalId }, function (data) {
        var productDropdown = $('#productDropdown');
        productDropdown.empty();
        productDropdown.append('<option value="">Select Product</option>');

        $.each(data, function (i, product) {
          productDropdown.append('<option value="' + product.id + '">' + product.name + '</option>');
        });
      });
    } else {
      $('#productDropdown').empty().append('<option value="">Select Product</option>');
      $('#priceInput').val('');
    }
  });
});

How can I recreate the visual look of base shiny navbarPage and tabPanel with a sidebar in bslib?

I am trying to use bslib to theme my Shiny application but I am having trouble understanding how to utilize the layout and card properties to create the base Shiny navbarPage and tabPanel look.

I have provided code below:

library(shiny)
library(bslib)
library(DT)
library(dplyr)

options(shiny.port = 8080)

test_theme <- bs_theme(
    bootswatch = "cosmo",
    version = 5,
    bg = "#FFFFFF", # Replaces default white with Adaptive off-white
    fg = "#000000", # Default black
    "navbar-bg" = "#0169d6",
    "navbar-light-bg" = "#0169d6",
    "navbar-light-color" = "#F6F6F6",
    "navbar-light-hover-color" = "#0B2663",
    "navbar-light-active-color" = "#F6F6F6",
    )

# UI/Server for Module_1
module_1_ui <- function(id) {
  ns <- NS(id)

  nav_panel(
    title = "Main",
    layout_columns(
      col_widths = c(3, 9),
      card(
        title = "Card 1",
        max_height = "150px",
        class = "well",
        textInput(ns("textInput"), 'Enter text')
      ),
      layout_columns(
        col_widths = 12,
        card(
          height = "100vh",
          style = "border: none;",
          title = "Card 2",
          uiOutput(ns('textOutput'))
        )
      )
    )
  )

  # tabPanel("Main", fluid = TRUE,
  #     sidebarLayout(
  #       sidebarPanel(
  #         textInput(ns('textInput'), 'Enter text')
  #       ),
  #       mainPanel(
  #         uiOutput(ns('textOutput'))
  #       )
  #     )
  # )
  
}

module_1_server <- function(id, session) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    output$textOutput <- renderUI({
      req(input$textInput)
      HTML(paste0('You entered: ', input$textInput))
    })
    
  })

}
# UI/Server for Module_2
module_2_ui <- function(id) {
  ns <- NS(id)

  nav_panel(
    title = "Side",
    layout_columns(
      col_widths = c(3, 9),
      card(
        title = "Card 1",
        class = "well",
        HTML("This always shows!"),
        br(),
        uiOutput(ns("selectUI")),
        conditionalPanel(
                  condition =  sprintf("input['%s'] == 'Test2'", ns("side_tabsets")),
                  uiOutput(ns("group_by_select")),
                  actionButton(ns("button3"), "Button 3")
                )
      ),
      layout_columns(
        col_widths = 12,
        card(
          height = "100vh",
          style = "border: none;",
          title = "Card 2",
          uiOutput(ns('sideOutput'))
        )
      )
    )
  )

  # tabPanel("Side", fluid = TRUE,
  #     sidebarLayout(
  #       sidebarPanel(
  #         HTML("This always shows!"),
  #         br(),
  #         uiOutput(ns("selectUI")),
  #         conditionalPanel(
  #                 condition =  sprintf("input['%s'] == 'Test2'", ns("side_tabsets")),
  #                 uiOutput(ns("group_by_select")),
  #                 actionButton(ns("button3"), "Button 3")
  #               )
  #       ),
  #       mainPanel(
  #         uiOutput(ns('sideOutput'))
  #       )
  #     )
  # )
}

module_2_server <- function(id, session) {

  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    output$selectUI <- renderUI({
      selectInput(ns("data_select"), "Select Data", choices = colnames(iris), multiple = TRUE)
    })

    output$sideOutput <- renderUI({
      tabsetPanel(
        id = ns("side_tabsets"),
        tabPanel(title = "Test1", br(), fluidRow(column(DT::DTOutput(ns("table")), width = 6))),
        tabPanel(title = "Test2", br(), fluidRow(column(DT::DTOutput(ns("group_by_table")), width = 6)))
      )
    })

    output$group_by_select <- renderUI({
      selectInput(ns("group_by_select"), "Group By", choices = colnames(iris))
    })

    output$table <- DT::renderDT({
      iris %>% select(input$data_select)
    })

    output$group_by_table <- DT::renderDT({
      NULL
    })

    observeEvent(input$button3, {
      output$group_by_table <- DT::renderDT({
        iris %>% select(input$data_select) %>% group_by(input$group_by_select) %>% summarise(n = n())
      })
    })
  })
}

# Overall UI
ui <- page_fluid(
  theme = test_theme,
  page_navbar(title = "",
    module_1_ui("main"),
    module_2_ui("side")
  )
)

# Overall Server
server <- function(input, output, session) {
  module_1_server("main", session)
  module_2_server("side", session)
}



shinyApp(ui = ui, server = server)

I want the appearance to match the commented out bit of my original Shiny code. The few things I cannot get to work well is having a floating sidebar using card that does not span the entire page:
enter image description here

Why do the dropdown menus get cutoff?
enter image description here

I want the sidebar to grow as more elements get added but not take up the entire page.

I have tried using the height, min_height, and max_height properties inside of card and it does not grow properly and always assumes the max_height.

Using Flask to create a turn based game against the computer

I am trying to create a pokemon battle game where the user can select their pokemon and then choose moves. The computer also does this. I have written my game logic in Python, and I am using fetch to send the user inputs through to my backend and returning data for the next move.

My issue is that I want the two functions that run the battle to loop until one pokemon faints. This involves new buttons in the DOM, adding event listeners to these and repeating the fetch requests. My two functions work, but not when I call them within the while loop.

Here is my battle.js code:

const form = document.getElementById('form')
const choiceSection = document.getElementById("userPokemonChoice")
const launchGame = document.getElementById("launchGame")
const launchGameForm = document.getElementById("launchGameForm")
const gamePlay = document.getElementById("gamePlay")
launchGame.style.display = "none"
let cpu_status = ""
let user_status = ""

function getPokemonStats() {

    form.addEventListener('submit', function(e){
        e.preventDefault();
    
        // Create a form with user input.
        const formData = new FormData(this); 
        // Add the name and value of the pressed button to the form.
        formData.append(e.submitter.name, e.submitter.value); 
        // Send a fetch request of type POST.
    
        // generate url
        const url = '/battle';
        fetch(url, { 
            method: 'post', 
            body: formData
        })
            .then(response => response.json()) // Read the response as json.
            .then(data => {
                displayPokemonStats(data)
                
            });
    
        choiceSection.style.display = "none"
        launchGame.style.display = "block"
    
    
    });
    

}

displayPokemonStats = function(data) {
    const pokemonStats = document.getElementById('stats')
    pokemonStats.innerText = 
        `You have chosen ${data[0]['name']}. ${data[0]['name']}'s hp is ${data[0]['hp']}. ${data[0]['name']}'s moves are ${data[0]['moves'].join(', ')}.
        The cpu has chosen ${data[1]['name']}.`
}


function cpuTurn(){
    launchGameForm.addEventListener('submit', function(e) {

        launchGame.style.display = "none"
        e.preventDefault();
    
        // Create a form with user input.
        const cpuFormData = new FormData(this); 
        // Add the name and value of the pressed button to the form.
        cpuFormData.append(e.submitter.name, e.submitter.value); 
        // Send a fetch request of type POST.
        const url = '/battle/launch';
        fetch(url, { 
            method: 'post', 
            body: cpuFormData
        }) 
        
            .then(response => response.json()) // Read the response as json.
            .then(data => {

                let user_status = data[2]
                const new_para = launchGameForm.appendChild(document.createElement("p"))
                if (user_status == 'alive'){
                    
                    new_para.innerText = `${data[1]['name']} used ${data[1]['move']} causing ${data[1]['damage']} damage.
                    ${data[0]['name']}'s hp was reduced to ${data[0]['hp']}.
                    Choose your next move!`
        
                    
                    launchGameForm.setAttribute("action", "/battle/launch/turn")
                    
                    new_button_1 = launchGameForm.appendChild(document.createElement("button"))
                    new_button_1.setAttribute("type", "submit")
                    new_button_1.setAttribute("name", "chooseMove")
                    new_button_1.setAttribute("value", `${data[0]['moves'][0]}`)
                    new_button_1.textContent = `${data[0]['moves'][0]}`
        
                    new_button_2 = launchGameForm.appendChild(document.createElement("button"))
                    new_button_2.setAttribute("type", "submit")
                    new_button_2.setAttribute("name", "chooseMove")
                    new_button_2.setAttribute("value", `${data[0]['moves'][1]}`)
                    new_button_2.textContent = `${data[0]['moves'][1]}`

                } else {
                    new_para.innerText = `${data[1]['name']} used ${data[1]['move']} causing ${data[1]['damage']} damage.
                    ${data[0]['name']} fainted!`

                }
                // console.log(data[2])
                //console.log(data[0]['moves'])
                console.log(`The user status is ${user_status}`)
                return user_status
                
            })
    })
}



function userTurn(){
    launchGameForm.addEventListener('submit', function(e) {
        e.preventDefault();
        // Create a form with user input.
        const userFormData = new FormData(this); 
        // Add the name and value of the pressed button to the form.
        userFormData.append(e.submitter.name, e.submitter.value); 
        // Send a fetch request of type POST.
        const url = '/battle/launch/turn';
        fetch(url, { 
            method: 'post', 
            body: userFormData
        })
        
            .then(response => response.json()) // Read the response as json.
            .then(data => {
                const new_para = launchGameForm.appendChild(document.createElement("p"))
                let cpu_status = data[2]

                if (cpu_status == "alive"){
                    new_para.innerText = `${data[0]['name']} used ${data[0]['move']} causing ${data[0]['damage']} damage.
                    ${data[1]['name']}'s hp was reduced to ${data[1]['hp']}.`
                } else {
                    new_para.innerText = `${data[0]['name']} used ${data[0]['move']} causing ${data[0]['damage']} damage.
                    ${data[1]['name']}' fainted!`
                }
                console.log(`The cpu status is ${cpu_status}`)
                return cpu_status
            });
            
    })

    
}


function battle(cpu_status, user_status) {
while (cpu_status == "alive" && user_status == "alive") {
cpuTurn()
userTurn()
   }
}

battle(cpu_status, user_status)

Here is my battle.py code:

import requests
import random
from flask import request, session
import db_utils as db


def get_pokemon():
    user_pokemon_name = request.form['userPokemonChoice']
    session['pokemon_name'] = user_pokemon_name
    user_pokemon = dict(name = f"{user_pokemon_name}", hp = get_hp_stat(user_pokemon_name), moves = get_initial_moves(user_pokemon_name) )
    # launch_battle_button = request.form['launchBattle']   
    starter_pokemon =["bulbasaur", "charmander", "squirtle"]
    """later: cpu chooses pokemon with type advantage"""
    available_pokemon = [pokemon for pokemon in starter_pokemon if pokemon != user_pokemon_name]
    cpu_pokemon_name = random.choice(available_pokemon)
    session['cpu_pokemon_name'] = cpu_pokemon_name
    cpu_pokemon = dict(name = f"{cpu_pokemon_name}", hp = get_hp_stat(cpu_pokemon_name), moves = get_initial_moves(cpu_pokemon_name) )
    poke_list = []
    poke_list.append(user_pokemon)
    poke_list.append(cpu_pokemon)
    print(poke_list)
    return poke_list

def get_response_from_api(pokemon_name):
    api_url = f"https://pokeapi.co/api/v2/pokemon/{pokemon_name}"
    response = requests.get(api_url)
    data = response.json()
    return data

def get_initial_moves(pokemon_name):
    data = get_response_from_api(pokemon_name)
    # filter data by level-learned-at: 1 and mover_learn_method: name: "level-up"
    """later: up to four moves are allocated to the pokemon"""
    move_names = []
    for i in range(len(data)):
        if data['moves'][i]['version_group_details'][0]['move_learn_method']['name'] == "level-up" and data['moves'][i]['version_group_details'][0]['level_learned_at'] == 1:
            move_names.append(data['moves'][i]['move']['name'])
    return move_names
            
def get_hp_stat(pokemon_name):
    # get pokemon hp
    data = get_response_from_api(pokemon_name)
    hp_stat = data['stats'][0]['base_stat']
    return hp_stat
    
def damage():
    return random.randint(1, 10)

def cpu_turn():
    user_status = "alive"
    cpu_pokemon_name = session['cpu_pokemon_name']
    cpu_pokemon = dict(name = f"{cpu_pokemon_name}", hp = get_hp_stat(cpu_pokemon_name), moves = get_initial_moves(cpu_pokemon_name) )
    user_pokemon_name = session['pokemon_name']
    user_pokemon = dict(name = f"{user_pokemon_name}", hp = get_hp_stat(user_pokemon_name), moves = get_initial_moves(user_pokemon_name) )

    if request.form['launchBattle']:
        cpu_move = random.choice(cpu_pokemon['moves'])
        cpu_damage = damage()
        user_pokemon['hp']-= cpu_damage
        cpu_pokemon_dict = dict(name = f"{cpu_pokemon_name}", move = cpu_move, damage = cpu_damage)
        user_pokemon_dict = dict(name = f"{user_pokemon_name}", moves = user_pokemon['moves'], hp = user_pokemon['hp'])
        cpu_move_result = []
        cpu_move_result.append(user_pokemon_dict)
        cpu_move_result.append(cpu_pokemon_dict)
        session['user_hp'] = user_pokemon['hp']

    if user_pokemon['hp'] > 0:
        print(f"{user_pokemon['name']}'s hp was reduced to {user_pokemon['hp']} ")
        print(" ")
        cpu_move_result.append(user_status)

        
    else:
        print(f"{user_pokemon['name']} fainted!")
        user_status = "fainted"
        cpu_move_result.append(user_status)

    return cpu_move_result
        
        
def user_turn():
    cpu_status = "alive"
    cpu_pokemon_name = session['cpu_pokemon_name']
    user_pokemon_name = session['pokemon_name']
    user_pokemon = dict(name = f"{user_pokemon_name}", hp = session['user_hp'], moves = get_initial_moves(user_pokemon_name) )
    cpu_pokemon = dict(name = f"{cpu_pokemon_name}", hp = get_hp_stat(cpu_pokemon_name), moves = get_initial_moves(cpu_pokemon_name) )
    
    user_move_choice = request.form['chooseMove']
    user_damage = damage()
    cpu_pokemon['hp']-=user_damage

    cpu_pokemon_dict = dict(name = f"{cpu_pokemon_name}", moves = cpu_pokemon['moves'], hp = cpu_pokemon['hp'])
    user_pokemon_dict = dict(name = f"{user_pokemon_name}", move = user_move_choice, damage = user_damage)
    user_move_result = []
    user_move_result.append(user_pokemon_dict)
    user_move_result.append(cpu_pokemon_dict)
    session['cpu_hp'] = cpu_pokemon['hp']

    if cpu_pokemon['hp'] > 0:
        print(f"{cpu_pokemon['name']}'s hp was reduced to {cpu_pokemon['hp']} ")
        print(" ")
        user_move_result.append(cpu_status)
    else:
        print(f"{cpu_pokemon['name']} fainted!")
        cpu_status = "fainted"
        user_move_result.append(cpu_status)

    return user_move_result

Here is my app.py code:

from flask import Flask, render_template, request, session
from flask_session import Session
import battle

app = Flask(__name__ ,
            static_url_path='',
            static_folder='../frontend/static',
            template_folder='../frontend/templates')

# CORS(app)
app.secret_key = 'BAD_SECRET_KEY'

@app.route("/")
def main():
    return render_template('index.html')
    
@app.route("/battle")
def battle_page():
    return render_template('battle.html') 

@app.route("/battle", methods=['POST', 'GET'])
def get_user_cpu_pokemon():
    return battle.get_pokemon()

@app.route("/battle/launch", methods=['GET', 'POST'])
def cpu_move():
    return battle.cpu_turn()

@app.route("/battle/launch/turn", methods=['GET', 'POST'])
def user_move():
    return battle.user_turn()


if __name__ == '__main__':
    app.run(debug=True, port=5001)

I have tried looking into async functions – I’m not sure if that’s my issue or whether I need to generate new app routes in my app.py. I’ve definitely bitten off more than I can chew and have debated just rewriting the game logic in js but I’d like to know if what I want to do is at least possible!

Any help would be muchly appreciated.

How to connect my React App to Azure sql database (using Endpoints)

I am struggling to connect to my Azure sql db, and error message on the console is pointing to this:

const saveSurveyResults = useCallback(async (formattedResponses) => {
const apiUrl = ${config.server}/saveSurveyResults;

console.log('Saving...');

try {
  const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ surveyResponses: formattedResponses }),
  });

  if (response.ok) {
    console.log('Survey results saved successfully');
  } else {
    console.error('Error:', response.statusText);
  }
} catch (error) {
  console.error('Error:', error);
}

}, []);

What could be the issue?

I would like to populate the Azure sql database with questions and answers user provided by the user.

VS Code’s tsserver was deleted by another application such as a misbehaving virus detection tool

i was working on a vs code extension, it was using the inbuilt typescript language server (tsserver.js)
But suddenly today i got an error VS Code’s tsserver was deleted by another application such as a misbehaving virus detection tool. Please reinstall VS Code.
I Reinstalled vs code , and checked these steps to ensure that tsserver.js was present . but now on running my extension , i get this warning The task ‘npm: watch’ cannot be tracked. Make sure to have a problem matcher defined,
and i no longer can use the typescript language server.
Kindly Assist.

I validated that the tsserver.js file is present in /Applications/Visual Studio Code.app/Contents/Resources/app/extensions/node_modules/typescript/lib/tsserver.js.
Following the steps from this discussion.
But i still cant use the typescript language server.

html 5 css flow chart, how can i add animated arrows?

I want to remove the static lines/arro3ws and add moving lines to make it like a flowchart

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Data Visionaries</title>
    <style>
        /* Overall Styling */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f0f0f0; /* Light background */
            color: #333333; /* Dark text */
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
        }

        .flowchart-container {
            text-align: center;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background-color: #ffffff; /* White background for the container */
            border-radius: 12px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); /* Light shadow */
            position: relative;
        }

        .flowchart-title {
            font-size: 36px; /* Larger font size for the title */
            color: #000000; /* Black color for the title */
            margin-bottom: 40px;
            font-weight: 700;
            text-transform: uppercase; /* Uppercase text for emphasis */
            font-family: 'Roboto', sans-serif; /* Stylish font for title */
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for text */
        }

        .flowchart {
            display: flex;
            align-items: center;
            gap: 40px;
            position: relative;
            justify-content: center;
            flex-wrap: wrap; /* Allows wrapping in case of smaller screens */
        }

        .database-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 40px;
            position: relative;
        }

        .step {
            background: linear-gradient(135deg, #a8d5ba, #68c1a8); /* Greenish gradient background */
            color: #333333; /* Dark text */
            padding: 15px 20px;
            border-radius: 10px; /* Rounded corners */
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); /* Soft shadow */
            width: 150px;
            text-align: center;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            position: relative;
            text-decoration: none;
            transition: all 0.3s ease; /* Smooth transition for hover effects */
            font-family: 'Arial', sans-serif; /* Creative font for steps */
            cursor: pointer; /* Pointer cursor for clickable elements */
        }

        .step:hover {
            background: linear-gradient(135deg, #68c1a8, #a8d5ba); /* Inverted gradient on hover */
            transform: scale(1.05); /* Slightly enlarge on hover */
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2); /* Enhanced shadow on hover */
        }

        .step h3 {
            margin: 10px 0;
            font-size: 16px; /* Slightly larger font size */
            font-weight: 600;
            color: #333333; /* Dark text color */
        }

        .step p {
            margin: 5px 0;
            font-size: 12px; /* Slightly smaller font size */
            color: #666666; /* Slightly lighter gray for text */
        }

        .step i {
            font-size: 24px; /* Larger icon size */
            margin-bottom: 10px;
            color: #ffcc00; /* Yellow color for icons */
        }

        /* SVG lines */
        .line {
            stroke: #333;
            stroke-width: 2;
            fill: none;
            stroke-dasharray: 5, 5;
            transition: stroke-dasharray 0.3s ease; /* Smooth line transition */
        }

        .line.active {
            stroke-dasharray: none; /* Remove dashes for moving effect */
            animation: moveLine 2s infinite linear; /* Animate the line */
        }

        @keyframes moveLine {
            0% {
                stroke-dashoffset: 0;
            }
            100% {
                stroke-dashoffset: 1000;
            }
        }
    </style>
</head>
<body>

    <div class="flowchart-container">
        <div class="flowchart-title">Data Visionaries</div> <!-- Updated Title -->
        <div class="flowchart">
            <!-- Database Container -->
            <div class="database-container">
                <!-- Existing Databases -->
                <div class="step" id="trading-dump">
                    <i class="fas fa-database"></i> <!-- Font Awesome Icon -->
                    <h3>Trading Dump</h3>
                    <p>Database</p>
                </div>

                <div class="step" id="advisory-dump">
                    <i class="fas fa-database"></i> <!-- Font Awesome Icon -->
                    <h3>Advisory Dump</h3>
                    <p>Database</p>
                </div>

                <!-- New Databases -->
                <div class="step" id="batch-volume-vs">
                    <i class="fas fa-database"></i> <!-- Font Awesome Icon -->
                    <h3>Batch Volume VS</h3>
                    <p>Database</p>
                </div>

                <div class="step" id="user-enrolled">
                    <i class="fas fa-database"></i> <!-- Font Awesome Icon -->
                    <h3>User Enrolled</h3>
                    <p>Database</p>
                </div>

                <div class="step" id="stock-activities">
                    <i class="fas fa-database"></i> <!-- Font Awesome Icon -->
                    <h3>Stock Activities</h3>
                    <p>Database</p>
                </div>
            </div>

            <!-- Python Script Step -->
            <div class="step" id="process-py">
                <i class="fas fa-code"></i> <!-- Font Awesome Icon -->
                <h3>process.py</h3>
                <p>Python Script</p>
                <p>Random Forest Model</p>
            </div>

            <!-- Prediction Step -->
            <div class="step" id="predicted-output">
                <i class="fas fa-chart-line"></i> <!-- Font Awesome Icon -->
                <h3>Predicted Output</h3>
                <p>Result</p>
            </div>

            <!-- SVG Lines -->
            <svg class="lines" width="100%" height="100%" style="position: absolute; top: 0; left: 0; pointer-events: none;">
                <line id="line-trading-dump" class="line" x1="150" y1="50" x2="500" y2="50"></line>
                <line id="line-advisory-dump" class="line" x1="150" y1="150" x2="500" y2="150"></line>
                <line id="line-batch-volume-vs" class="line" x1="150" y1="250" x2="500" y2="250"></line>
                <line id="line-user-enrolled" class="line" x1="150" y1="350" x2="500" y2="350"></line>
                <line id="line-stock-activities" class="line" x1="150" y1="450" x2="500" y2="450"></line>
            </svg>
        </div>
    </div>

    <!-- Link to Font Awesome for icons -->
    <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>

    <script>
        document.querySelectorAll('.line').forEach(line => {
            line.addEventListener('click', () => {
                line.classList.toggle('active'); // Toggle movement animation
            });
        });
    </script>

</body>
</html>

how can i add moving arrow line to this?
I want to remove the static lines/arro3ws and add moving lines to make it like a flowchart