How to write the JavaScript Discorver Readers in Stripe?

I’m developing an POS system and I would like to connect a Stripe physical reader, not a simulation.
Here is my JavaScript codes for initializing, Redears discovering and connecting reader.

// Initialize Stripe Terminal
const terminal = StripeTerminal.create({
    onFetchConnectionToken: async () => {
        try {
            const response = await fetch("http://127.0.0.1:8000/create_connection_token/", { method: 'POST' });
            if (!response.ok) {
                throw new Error("Failed to fetch connection token");
            }
            const { secret } = await response.json();
            return secret;
        } catch (error) {
            console.error("Error fetching connection token:", error);
            throw error;
        }
    },
    onUnexpectedReaderDisconnect: () => {
        console.error("Reader unexpectedly disconnected.");
        alert("Le terminal s'est déconnecté de manière inattendue. Veuillez vérifier la connexion et réessayer.");
    },
});

console.log("Stripe Terminal initialized.");

// Discover readers
async function discoverReaders() {
    try {
        console.log("Discovering readers...");

        const config = { 
            simulated: false, 
            location: "LOCATION_ID" 
        };

        const discoverResult = await terminal.discoverReaders(config);
        console.log("Discover Result:", discoverResult);

        if (discoverResult.error) {
            console.error('Error discovering readers:', discoverResult.error.message);
            alert('Erreur lors de la découverte des lecteurs. Vérifiez votre configuration réseau.');
            return null;
        }

        if (discoverResult.discoveredReaders.length === 0) {
            console.warn("No available readers. Ensure the terminal is powered on and connected.");
            alert("Aucun terminal trouvé. Vérifiez la connectivité et la configuration réseau.");
            return null;
        }

        console.log("Discovered readers:", discoverResult.discoveredReaders);
        alert("Lecteurs découverts avec succès.");
        return discoverResult.discoveredReaders[0];
    } catch (error) {
        console.error("Error during reader discovery:", error);
        alert("Une erreur inattendue s'est produite lors de la découverte des lecteurs.");
        return null;
    }
}

// Connect to a reader
async function connectReader(reader) {
    try {
        console.log("Attempting to connect to reader:", reader.label);

        // Connect to the selected reader
        const connectResult = await terminal.connectReader(reader);

        // Handle connection errors
        if (connectResult.error) {
            console.error("Failed to connect:", connectResult.error.message);
            alert(`Connexion échouée : ${connectResult.error.message}`);
            return false;
        }

        console.log("Connected to reader:", connectResult.reader.label);
        alert(`Connecté au lecteur : ${connectResult.reader.label}`);
        return true;
    } catch (error) {
        console.error("Error during reader connection:", error);
        alert("Une erreur inattendue s'est produite lors de la connexion au terminal. Consultez la console pour plus de détails.");
        return false;
    }
}

// Example usage: Discover and connect to a reader
async function handleReaderSetup() {
    const reader = await discoverReaders();
    if (reader) {
        await connectReader(reader);
    }
}

I was able to connect the reader using the Stripe API, and from my stripe I can see if reader is or not online.
However, when I run the application and try to send the money to the reader for payment, it’s showing Aucun terminal trouvé. Vérifiez la connectivité et la configuration réseau. which means that in English No terminal found. Check connectivity and network configuration. The confusing thing is, when I run this:

import stripe
stripe.api_key = "sk_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

try:
    # List all readers
    readers = stripe.terminal.Reader.list()
    print("Readers:", readers)
except stripe.error.StripeError as e:
    print("Stripe error:", e)
except Exception as e:
    print("An unexpected error occurred:", e)

I’m getting this output:

Readers: {
  "data": [                                                                                                                                                                                                          {                                                                                                                                                                                                                  "action": null,                                                                                                                                                                                                  "device_sw_version": "2.27.7.0",                                                                                                                                                                                 "device_type": "bbpos_wisepos_e",
      "id": "tmr_XXXXXXXXXXXXXX",
      "ip_address": "x.0.0.xxx",
      "label": "Testing_Reader",
      "last_seen_at": 1735518518163,
      "livemode": true,
      "location": "tml_ZZZZZZZZZZZZ",
      "metadata": {},
      "object": "terminal.reader",
      "serial_number": "YYYYYYYYYYYYY",
      "status": "online"
    }
  ],
  "has_more": false,
  "object": "list",
  "url": "/v1/terminal/readers"
}

In addition, this command: stripe terminal readers list
shows this result:

{
  "object": "list",
  "data": [
    {
      "id": "tmr_XXXXXXXXXXXXXX",
      "object": "terminal.reader",
      "action": null,
      "device_sw_version": "2.27.7.0",
      "device_type": "bbpos_wisepos_e",
      "ip_address": "x.0.0.xxx",
      "label": "Testing_Reader",
      "last_seen_at": 1735517252951,
      "livemode": true,
      "location": "tml_ZZZZZZZZZZZZ",
      "metadata": {},
      "serial_number": "YYYYYYYYYYYYY",
      "status": "online"
    }
  ],
  "has_more": false,
  "url": "/v1/terminal/readers"

I really don’t understand, why clicking in this button

<button type="button" id="send-to-terminal" class="btn btn-primary" data-order-id="{{ order.id }}"> Envoyer au terminal</button> gives me the error I mentioned above.

For more details, I’ve this service as well:

import stripe
import logging
from decimal import Decimal
from django.conf import settings

class PaymentService:
    def __init__(self):
        """Initialize the PaymentService with the Stripe API key."""
        stripe.api_key = settings.STRIPE_SECRET_KEY
        self.logger = logging.getLogger(__name__)

    def get_online_reader(self):
        """
        Fetch the first online terminal reader from Stripe.
        :return: Stripe Terminal Reader object.
        :raises: ValueError if no online reader is found.
        """
        try:
            readers = stripe.terminal.Reader.list(status="online").data
            if not readers:
                self.logger.error("Aucun lecteur de terminal en ligne trouvé.")
                raise ValueError("Aucun lecteur de terminal en ligne trouvé.")
            return readers[0]  # Return the first online reader
        except stripe.error.StripeError as e:
            self.logger.error(f"Erreur Stripe lors de la récupération des lecteurs: {str(e)}")
            raise Exception(f"Erreur Stripe: {str(e)}")

    def create_payment_intent(self, amount, currency="CAD", payment_method_types=None, capture_method="automatic"):
        """
        Create a payment intent for a terminal transaction.
        :param amount: Decimal, total amount to charge.
        :param currency: str, currency code (default: "CAD").
        :param payment_method_types: list, payment methods (default: ["card_present"]).
        :param capture_method: str, capture method for the payment intent.
        :return: Stripe PaymentIntent object.
        """
        try:
            if payment_method_types is None:
                payment_method_types = ["card_present"]

            payment_intent = stripe.PaymentIntent.create(
                amount=int(round(amount, 2) * 100),  # Convert to cents
                currency=currency.lower(),
                payment_method_types=payment_method_types,
                capture_method=capture_method  # Explicitly include this argument
            )
            self.logger.info(f"PaymentIntent created: {payment_intent['id']}")
            return payment_intent
        except stripe.error.StripeError as e:
            self.logger.error(f"Stripe error while creating PaymentIntent: {str(e)}")
            raise Exception(f"Stripe error: {str(e)}")
        except Exception as e:
            self.logger.error(f"Unexpected error while creating PaymentIntent: {str(e)}")
            raise Exception(f"Unexpected error: {str(e)}")

    
    def send_to_terminal(self, payment_intent_id):
        """
        Send a payment intent to the online terminal reader for processing.
        :param payment_intent_id: str, ID of the PaymentIntent.
        :return: Stripe response from the terminal reader.
        """
        try:
            # Retrieve the Reader ID from settings
            reader_id = settings.STRIPE_READER_ID  # Ensure this is correctly set in your configuration
            
            # Send the payment intent to the terminal
            response = stripe.terminal.Reader.process_payment_intent(
                reader_id, {"payment_intent": payment_intent_id}
            )
            
            self.logger.info(f"PaymentIntent {payment_intent_id} sent to reader {reader_id}.")
            return response
        except stripe.error.StripeError as e:
            self.logger.error(f"Erreur Stripe lors de l'envoi au terminal: {str(e)}")
            raise Exception(f"Erreur Stripe: {str(e)}")
        except Exception as e:
            self.logger.error(f"Unexpected error while sending to terminal: {str(e)}")
            raise Exception(f"Unexpected error: {str(e)}")

and these views:

@login_required
def send_to_terminal(request, order_id):
    """
    Send the payment amount to the terminal.
    """
    if request.method == "POST":
        try:
            # Validate amount
            amount = Decimal(request.POST.get('amount', 0))
            if amount <= 0:
                return JsonResponse({'success': False, 'error': 'Montant non valide.'}, status=400)

            # Create PaymentIntent
            payment_intent = stripe.PaymentIntent.create(
                amount=int(amount * 100),
                currency="CAD",
                payment_method_types=["card_present"]
            )

            # List online readers dynamically
            readers = stripe.terminal.Reader.list(status="online").data
            if not readers:
                return JsonResponse({'success': False, 'error': 'Aucun lecteur en ligne trouvé.'}, status=404)

            # Use the first available reader
            reader = readers[0]

            # Send PaymentIntent to the terminal
            response = stripe.terminal.Reader.process_payment_intent(
                reader["id"], {"payment_intent": payment_intent["id"]}
            )

            # Handle the response
            if response.get("status") == "succeeded":
                return JsonResponse({
                    'success': True,
                    'payment_intent_id': payment_intent["id"],
                    'message': 'Paiement envoyé avec succès au terminal.'
                })
            else:
                return JsonResponse({
                    'success': False,
                    'error': response.get("error", "Erreur inconnue du terminal.")
                }, status=400)

        except stripe.error.StripeError as e:
            return JsonResponse({'success': False, 'error': f"Erreur Stripe : {str(e)}"}, status=500)

        except Exception as e:
            return JsonResponse({'success': False, 'error': f"Une erreur inattendue s'est produite: {str(e)}"}, status=500)

    return JsonResponse({'success': False, 'error': 'Méthode non autorisée.'}, status=405)



@csrf_exempt  # Allow requests from the frontend if CSRF tokens are not included
def create_connection_token(request):
    try:
        # Create a connection token
        connection_token = stripe.terminal.ConnectionToken.create()
        return JsonResponse({"secret": connection_token.secret})
    except stripe.error.StripeError as e:
        # Handle Stripe API errors
        return JsonResponse({"error": str(e)}, status=500)
    except Exception as e:
        # Handle other unexpected errors
        return JsonResponse({"error": f"Unexpected error: {str(e)}"}, status=500)

Express.js API Integration with SkyScanner API Fails to retrieve flights data

I’m working on integrating the Skyscanner Flights Scraper API using Express.js and Axios. The goal is to fetch flight data using the /flights/search-everywhere endpoint. Here’s what I’ve done so far:

Successfully obtained the fromEntityId from the /flights/auto-complete endpoint.
Attempted to use this fromEntityId to search flights via /flights/search-everywhere.
When I test this in the RapidAPI Playground, it works perfectly and returns valid flight data. However, when I run the same query through my local server and Postman, it always returns:

{
“message”: “No flights found”
}

Observations:
In RapidAPI: The request returns valid flight data.
In Postman: The request always responds with “message”: “No flights found”.
I suspect there’s an issue with how I’m passing the fromEntityId or how Axios handles the request, but I’m not sure what I’m doing wrong.
Things I’ve Tried:
Verified that the API key and host are correct.
Double-checked the request headers and parameters against the RapidAPI playground.
Logged the fromEntityId to ensure it’s being received correctly in the server.

/* server.js */

app.post('/flights', async (req, res) => {
    const { fromEntityId } = req.body;

    try {
        const response = await axios.get(`https://${API_HOST}/flights/search-everywhere`, {
            headers: {
                'X-RapidAPI-Host': API_HOST,
                'X-RapidAPI-Key': API_KEY,
            },
            params: {
                query: fromEntityId,
            },
        });

        const flights = response.data?.data?.results || null;

        if (!flights) {
            return res.json({ message: 'No flights found' });
        }

        res.json(flights);
    } catch (error) {
        console.error('Error fetching flights:', error);
        res.status(500).json({ message: 'Error fetching flights. Please try again.' });
    }
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});


PostMan Doesn’t WorkAPI Website Works

Could you please kindly help? Thank you!

Observations:
In RapidAPI: The request returns valid flight data.
In Postman: The request always responds with “message”: “No flights found”.
I suspect there’s an issue with how I’m passing the fromEntityId or how Axios handles the request, but I’m not sure what I’m doing wrong.
Things I’ve Tried:
Verified that the API key and host are correct.
Double-checked the request headers and parameters against the RapidAPI playground.
Logged the fromEntityId to ensure it’s being received correctly in the server.

How to render nextjs component inside an object string?

I have installed lucide react icon package and stored each JSX element tag in object within a string as “ICON” and loop through each of them through the array map.

My problem is, how i can render and execute it as a JSX tag? and not a string. Currently it is rendered as a normal string in the browser.

Menu items.

export const MenuItems = [
{
    label: "Home",
    icon: "<House color={black} size={32} />",
    url: "/",
},
{
    label: "About",
    icon: "<ContactRound />",
    url: "/about",
},
{
    label: "Contact",
    icon: "<Phone />",
    url: "/contact",
},
];

Main Menu Component.

import Link from "next/link";
import { MenuItems } from "./MenuItems";
import Image from "next/image";
const Menu = () => {
return (
    <div className=''>
        {MenuItems.map(i => (
            <div className="">
                <Link href={i.url} key={i.label}>
                    {/*<Image src={i.icon} alt="icon" width={32} height={32}/>*/}
                    {i.icon}

                    <span>{i.label}</span>
                </Link>
            </div>
        ))}
    </div>
);
}
export default Menu;

Screenshot

enter image description here

CORS preflight and request works, but browser console replay request fails [duplicate]

I’m not new to CORS in the world of server admin but in the browser (Chrome 131, Windows) I am not as familiar.

I use a web app at tools.siteground.com. There is a button which when clicked uses fetch() to submit a PUT request to a separate domain, xyz.siteground.biz. When clicking the button the CORS request works, and in devtools’ network inspector we see the preflight and PUT requests both succeed with 200 status.

I want to replay this request in the browser on demand.

If I right-click the PUT request, I can “Copy as fetch” and paste it into the console. Since the original request was also a fetch() request, and I am pasting and running the same request in the console for the same document, it should operate exactly as if the page executed the request a second time. But, it fails.

When reviewing the network inspector we see a second preflight request, which succeeds, followed by the PUT request initiated in the console, which fails due to CORS error. The only notable difference from the prior, page-initiated, PUT request is the lack of any set cookies.

When reviewing the console error output, we see that a particular response header in the preflight response is considered problematic given that the request uses the header credentials:include

Q1: Why is there a second preflight request?

Q2: What exactly is going on here?

Q3: Is there any way to make it work in the browser or the only option is curl or similar?

Chrome browser network inspector
Chrome browser console error

Using requests to post to a website after simulating an OnClick event without a headless browser

I have several constraints due to packages and software being locked down in my company.

I am working with a website that has an onClick event that reveals a table. Before the onClick event (i.e. the initial page of the website), I can write a POST request that essentially mimics the action of the onClick event, returning the page post the onClick event. However, additional POST requests or GET requests, even within the same session,
are interacting against the original page. I have not “clicked” the button to reveal the JavaScript that the initial POST request reveals in the requests session. The click event does not change the URL (so there are no parameters to load against; it just loads the HTML directly onto the page).

My question is: How would I resolve this without using a headless browser or changing the website (and adding something like AJAX). My idea was to use the content from the initial response as the “website” I POST against, but I don’t how to make that work (or if it can work).

Some simplified code below to describe the situation:

import requests
url = "someurl.com"

session = requests.Session()
headers = {"some keys and values"}
payload1 = {"submitBtn": "submit"}
initialRequest = session.post(url, data=payload1, headers=headers)
// initialRequest.content -> This returns the "correct" page (the page the javascript loads after the onClick event)
payload2 = {"newData": "3", "saveBtn":"save"}
followUpRequest =  session.post(url, data=payload2, headers=headers) // This fails because Requests is loading the initial page again (demonstrated by a session.get(url) Request that returns the initial page).

Is this a way to POST against the content from “initialRequest” on the same URL? Again the URL does not change at all (so there’s no easy parameters I can throw in). Any ideas? Other mainstream python libraries would work but Selenium is not an option.

Error integrating Privy’s Solana Embedded Wallets with Anchor Framework

I am building my app with privy’s solana embedded wallets and anchor framework, when I try to initialize my Solana Program – it shows an error

Any idea what might be causing this?

I believe error is occurring here

        const rpsProgram = new anchor.Program(
          IDL,
          new PublicKey(PROGRAM_ID),
          provider
        );

Here is the full function

 const initializeProgram = async () => {
      if (!solanaWallet?.address) {
        console.log("Waiting for wallet...");
        return;
      }

      try {
        console.log("Initializing with wallet address:", solanaWallet.address);
        console.log("Full wallet object:", solanaWallet);
        console.log("IDL:", IDL);
        
        const connection = new Connection(DEVNET_ENDPOINT);
        console.log("Connection created");
        
        const walletAdapter = {
          publicKey: new PublicKey(solanaWallet.address),
          signTransaction: solanaWallet.signTransaction,
          signAllTransactions: async (transactions) => {
            return Promise.all(transactions.map(tx => solanaWallet.signTransaction(tx)));
          },
        };
        console.log("Wallet adapter created:", walletAdapter);

        const provider = new anchor.AnchorProvider(
          connection,
          walletAdapter,
          { commitment: 'confirmed' }
        );
        console.log("Provider created:", provider);
        console.log("IDL:", IDL);
        anchor.setProvider(provider);
        console.log("wallet id", new PublicKey(solanaWallet.address));
        console.log("Program ID:", new PublicKey(PROGRAM_ID));
        console.log("Pro")
        const rpsProgram = new anchor.Program(
          IDL,
          new PublicKey(PROGRAM_ID),
          provider
        );
        
        console.log("Program created:", rpsProgram);
        setProgram(rpsProgram);
      } catch (err) {
        console.error('Failed to initialize RPS program:', err);
        console.error('Error details:', {
          name: err.name,
          message: err.message,
          stack: err.stack
        });
        toast.error('Failed to initialize game program');
      }
    };

    initializeProgram();
  }, [solanaWallet?.address]);

Here are my log statements if it helps

Wallet adapter created: 
{publicKey: _PublicKey2, signTransaction: ƒ, signAllTransactions: ƒ}
RPSProvider.tsx:52 Provider created: 
_AnchorProvider {connection: Connection, wallet: {…}, opts: {…}, publicKey: _PublicKey2}
RPSProvider.tsx:53 IDL: 
{version: '0.1.0', name: 'rps_game', instructions: Array(8), accounts: Array(2), types: Array(2), …}
RPSProvider.tsx:55 wallet id 
_PublicKey2 {_bn: BN}
_bn
: 
BN {negative: 0, words: Array(11), length: 10, red: null}
Symbol(Symbol.toStringTag)
: 
(...)
[[Prototype]]
: 
Struct2
RPSProvider.tsx:56 Program ID: 
_PublicKey2 {_bn: BN}
_bn
: 
BN {negative: 0, words: Array(11), length: 10, red: null}
Symbol(Symbol.toStringTag)
: 
(...)
[[Prototype]]
: 
Struct2


RPSProvider.tsx:67 Failed to initialize RPS program: TypeError: Cannot read properties of undefined (reading '_bn')
    at initializeProgram (RPSProvider.tsx:58:28)
    at RPSProvider.tsx:77:5
initializeProgram   @   RPSProvider.tsx:67
(anonymous) @   RPSProvider.tsx:77
RPSProvider.tsx:68 Error details: 
{name: 'TypeError', message: "Cannot read properties of undefined (reading '_bn')", stack: 'TypeError: Cannot read properties of undefined (re….vite/deps/chunk-IYNIHSXD.js?v=fbe42c5d:18119:15)'}
initializeProgram   @   RPSProvider.tsx:68
(anonymous) @   RPSProvider.tsx:77

Sharing my types file as well

export const IDL: RpsGame = {
  "version": "0.1.0",
  "name": "rps_game",
  "instructions": [ // instructions]
}
export type RpsGame = {
  "version": "0.1.0",
  "name": "rps_game",
  "instructions": [ // instructions]
}

Namespace for jQuery plugin

I have a jQuery plugin I created for my needs. Now all functions are in global namespace which isn’t good, I would like to move them to hoo.account namespace.

Here how my code looks right now:

(($) => {
    $.fn.toggleActive = function(active) {
        this.toggleClass("active", active);
        this.children(".data__form-activator").toggle(!active);
        this.children(".data__form-btn").toggleClass("visible", active);
        this.children(".data__flex-row").toggleClass("_m-none", !active);
        this.find("input, select").prop("disabled", !active);

        return this;
    };

    $.fn.activate = function() {
        return this.toggleActive(true);
    };

    $.fn.deactivate = function() {
        return this.toggleActive(false);
    };
})(jQuery);

Now I’m calling $(...).activate(), but I wanna call it $(...)hoo.account.activate().

Thanks in advance!

passing parameter to Function inside of swal after $.ajax call

I am new to Javascript and jQuery. I am running into an issue passing data to my function, ProcessFileFromGrid() in the onClick event in JS. It all tests out fine, but then I wanted to do something with the result sent back from the Ajax call.

In this example I call API /uploadPhysical and then I check for sucess: or error:. That all works great.
In the Success: callback, I display a question to the user, “Upload Complete! Do you want to process your files?”. If they say yes, I do a series of things in the onClick event. One of the things that I do is pass “data” to the ProcessFilesFromGrid() function. It works fine without the data being passed, so I know its how I am passing “data”. data comes back from the call. I have tried different things, but I get a JS errors in F12 console. I also tried: ProcessFileFromGrid(‘” + data + “‘

How would I do this?

$.ajax({
    type: "POST",
    mimetype: 'multipart/form-data',
    url: commonUrl + "api/FileTransfer/UploadPhysical",
    headers: {
        'Authorization': "Bearer " + token,
    },
    //dataType: 'json',
    data: formData,
    processData: false,
    contentType: false,
    async: true,
    // cache: false,
    // timeout: 600000,
    success: function (data) {
         
         var screenExitMessage = "Upload Completed!<br/><br/>Do you want to process your files ?";
        alert(data);
         swal.fire({
            html:
                "<button type='button' role='button' tabindex='0' class='btn swal2-styled btn-outline btn-outline-success' onclick='swal.close(); ProcessFilesFromGrid(data);'><i class='fa-solid fa-check fs-1'></i>Yes</button>" +
                "<button type='button' role='button' tabindex='0' class='btn swal2-styled btn-light-primary' onclick='swal.close(); ReloadFileGrids();'>No</button>",
            title: screenExitMessage,
            text: screenExitMessage,
            icon: 'question',
            showCancelButton: false,
            showConfirmButton: false,
        }).then(function () {
                
            // swal.close();
              // ReloadFileGrids();
        });
    },
    error: function (e) {
       
        swal.fire({
            text: e.responseText,
            icon: "error",
            buttonsStyling: false,
            confirmButtonText: "OK",
            customClass: {
                confirmButton: "btn font-weight-bold btn-light-primary"
            }
        })
    }
});
}
else {
    swal.fire({
    text: "Please select a file to upload",
    icon: "error",
    buttonsStyling: false,
    confirmButtonText: "OK",
    customClass: {
        confirmButton: "btn font-weight-bold btn-light-primary"
        }
    })
}

function ProcessFilesFromGrid(databaseName) {
enableControls(false, false);
var username = localStorage.getItem("Username");
var orgId = $("#ddlBorrowerName").val();
var processOption = $("#ddlProcessOption").val();
var databaseOption = $("#ddlDatabaseOption").val();
if (databaseName) {
    databaseOption = databaseName;
}

console.log("Process Option: " + processOption);
console.log("Database Option: " + databaseOption);

var apigetlink = "/Upload/ProcessFiles?Username=" + username + "&OrgId=" + orgId + "&ProcessOption=" + processOption + "&DatabaseOption=" + databaseOption;

AjaxPostBackendAsyncCallback(apigetlink, model, function (data) {
    if (data && data.status == 1) {
        swal.fire({
            html: data.message,
            icon: "success",
            icon: "success",
            buttonsStyling: false,
            confirmButtonText: "OK",
            customClass: {
                confirmButton: "btn font-weight-bold btn-light-primary"
            }
        });
        ReloadFileGrids();
    }
    else {
        var message = data.message;
        message = "Processing Issues!<br /><br />";
        message += data.message.replaceAll("<br />","<br /><br />");
        swal.fire({
            html: message,
            icon: "info",
            buttonsStyling: false,
            confirmButtonText: "OK",
            customClass: {
                confirmButton: "btn font-weight-bold btn-light-primary"
            }
        });
        ReloadFileGrids();
    }

}, errorCallback);

}

I don’t want to use ‘if’

I want to make a copy of the profile photo upload area used on Instagram and Upwork that works in the same way. I’ve been trying for a while and the only solution I could find is as follows. I had to use a lot of ifs but I don’t want to do that. Is there a simpler or more logical or easier way or something better that you think is better like this?

I think I need to change the handleMouseMove function, please help !!

import React, { ChangeEvent, useEffect, useRef, useState } from "react";
import { Dialog, DialogContent, DialogTitle } from "./ui/dialog";
import { Button } from "./ui/button";
import { cn } from "@/lib/utils";
import "react-image-crop/dist/ReactCrop.css";

function EditProfilePhotoDialog({ open, setOpen, profilePic }: { open: boolean; setOpen: React.Dispatch<React.SetStateAction<boolean>>; profilePic: React.Dispatch<React.SetStateAction<string>> }) {
   const fileInputRef = useRef<HTMLInputElement | null>(null);
   const [scale, setScale] = useState(1);
   const [error, setError] = useState("");
   const [imgSrc, setImgSrc] = useState<string | null>(null);
   const canvasRef = useRef<HTMLCanvasElement | null>(null);
   const imgRef = useRef<HTMLImageElement | null>(null);
   const [position, setPosition] = useState({ x: 0, y: 0 }); // Canvas'ın konumunu takip etmek için state

   // Mouse sürükleme olaylarını takip etmek için gerekli state'ler
   const [dragging, setDragging] = useState(false);
   const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });

   console.log("render");

   const handleImageUpload = (e: ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (file) {
         const reader = new FileReader();
         reader.onload = () => {
            const img = new window.Image();
            img.onload = () => {
               setImgSrc(reader.result as string);

               const canvas = document.createElement("canvas");
               canvasRef.current = canvas;
               const container = document.getElementById("canvas-container");
               if (container && canvas) {
                  container.appendChild(canvas);

                  const orgWidth = img.width;
                  const orgHeight = img.height;

                  const scl = 300 / Math.min(orgWidth, orgHeight);

                  const newWidth = orgWidth * scl;
                  const newHeight = orgHeight * scl;

                  canvas.width = newWidth;
                  canvas.height = newHeight;

                  canvas.className = `absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2  ${dragging ? "cursor-grabbing" : "cursor-grab"}`;
                  canvas.id = "cnv";

                  const ctx = canvas.getContext("2d");
                  if (ctx) {
                     ctx.clearRect(0, 0, canvas.width, canvas.height);
                     ctx.save();
                     ctx.globalAlpha = 0.3;
                     ctx.scale(scale, scale);
                     ctx.drawImage(img, 0, 0, newWidth, newHeight);
                     ctx.restore();
                  }
               }
               imgRef.current = img; // Resmi referansla sakla
            };
            img.src = reader.result as string;
         };
         reader.readAsDataURL(file);
      }
   };

   useEffect(() => {
      const canvas = canvasRef.current;
      const container = document.getElementById("canvas-container");

      if (canvas && container) {
         const containerRect = container.getBoundingClientRect();
         const canvasRect = canvas.getBoundingClientRect();

         const handleMouseDown = (e: MouseEvent) => {
            setDragging(true);
            setPosition({ x: canvas.offsetLeft, y: canvas.offsetTop });
            setStartPosition({ x: e.clientX, y: e.clientY });
         };

         const handleMouseMove = (e: MouseEvent) => {
            if (!dragging) return;

            let newX = position.x;
            let newY = position.y;

            if (canvasRect.width === 300) {
               newX = position.x;
            }

            if (canvasRect.height === 300) {
               newY = position.y;
            }

            let kilitTop = canvasRect.top <= containerRect.top - 10;
            let kilitLeft = canvasRect.left <= containerRect.left - 10;
            let kilitBot = canvasRect.bottom >= containerRect.bottom + 10;
            let kilitRight = canvasRect.right >= containerRect.right + 10;

            if (kilitTop && kilitBot) {
               newY = position.y + (e.clientY - startPosition.y);
            }
            if (kilitLeft && kilitRight) {
               newX = position.x + (e.clientX - startPosition.x);
            }
            if (canvasRect.height !== 300 && !kilitTop && e.clientY - startPosition.y < 0) {
               newY = position.y + (e.clientY - startPosition.y);
            }
            if (canvasRect.height !== 300 && !kilitTop && canvasRect.top > containerRect.top) {
               newY = position.y + (containerRect.top - canvasRect.top);
            }
            if (canvasRect.height !== 300 && !kilitBot && e.clientY - startPosition.y > 0) {
               newY = position.y + (e.clientY - startPosition.y);
            }
            if (canvasRect.height !== 300 && !kilitBot && canvasRect.bottom < containerRect.bottom) {
               newY = position.y - (canvasRect.bottom - containerRect.bottom);
            }
            if (canvasRect.width !== 300 && !kilitLeft && e.clientX - startPosition.x < 0) {
               newX = position.x + (e.clientX - startPosition.x);
            }
            if (canvasRect.width !== 300 && !kilitLeft && canvasRect.left > containerRect.left) {
               newX = position.x + (containerRect.left - canvasRect.left);
            }
            if (canvasRect.width !== 300 && !kilitRight && e.clientX - startPosition.x > 0) {
               newX = position.x + (e.clientX - startPosition.x);
            }
            if (canvasRect.width !== 300 && !kilitRight && canvasRect.right < containerRect.right) {
               newX = position.x + (containerRect.right - canvasRect.right);
            }

            setPosition({ x: newX, y: newY });
            setStartPosition({ x: e.clientX, y: e.clientY });
         };

         const handleMouseUp = () => setDragging(false);

         const handleMouseLeave = () => setDragging(false);

         canvas.addEventListener("mousedown", handleMouseDown);
         window.addEventListener("mousemove", handleMouseMove);
         window.addEventListener("mouseup", handleMouseUp);
         canvas.addEventListener("mouseleave", handleMouseLeave);

         return () => {
            if (canvas) {
               canvas.removeEventListener("mousedown", handleMouseDown);
               window.removeEventListener("mousemove", handleMouseMove);
               window.removeEventListener("mouseup", handleMouseUp);
               canvas.removeEventListener("mouseleave", handleMouseLeave);
            }
         };
      }
   }, [imgSrc, dragging, position, setPosition]);

   useEffect(() => {
      const canvas = canvasRef.current;
      if (canvas) {
         canvas.style.left = `${position.x}px`;
         canvas.style.top = `${position.y}px`;
      }
   }, [position]);

   useEffect(() => {
      const canvas = canvasRef.current;
      if (canvas) canvas.style.cursor = dragging ? "grabbing" : "grab";
   }, [dragging]);

   useEffect(() => {
      const canvas = canvasRef.current;

      if (canvas) {
         setPosition({ x: position.x, y: position.y });
         canvas.style.transform = `scale(${scale})`;
         canvas.style.transformOrigin = "center";
      }
   }, [scale]);

   return (
      <Dialog open={open} onOpenChange={setOpen}>
         <DialogContent className="w-11/12 md:w-[700px] max-w-[700px] min-h-[70vh] font-poppins" aria-describedby={undefined}>
            <DialogTitle className="sr-only">Profil fotoğrafını düzenle</DialogTitle>

            <div className="flex items-center space-x-3">
               <h1 className="tracking-wide">Fotoğrafı düzenle</h1>
            </div>
            <div className="flex">
               <div className="space-y-5 w-full flex flex-col items-center justify-center">
                  <div className="w-[300px] h-[300px] relative overflow-hidden rounded-full" id="canvas-container">
                     <label
                        htmlFor="image-upload"
                        className={cn(
                           "w-full h-full rounded-full border-slate-600 border-2 border-dashed flex items-center justify-center overflow-hidden",
                           imgSrc === null ? "cursor-pointer" : "pointer-events-none"
                        )}
                     >
                        {!imgSrc && <p className="text-xl font-semibold cursor-pointer">Bir resim yükleyin</p>}
                     </label>
                     <input ref={fileInputRef} type="file" accept="image/" id="image-upload" className={cn("hidden")} onChange={handleImageUpload} />
                  </div>
               </div>

               <div className="hidden sm:block p-5 mt-10">
                  {imgSrc && (
                     <input
                        type="range"
                        value={scale}
                        max={2}
                        min={1}
                        step={0.1}
                        onChange={(e) => {
                           setScale(Number(e.target.value));
                        }}
                     />
                  )}
                  <div className="flex items-center justify-center space-x-2">
                     <div className="w-24 h-24">
                        <div className="w-full h-full rounded-full bg-gray-200"></div>
                     </div>
                     <div className="w-16 h-16">
                        <div className="w-full h-full rounded-full bg-gray-200"></div>
                     </div>
                     <div className="w-12 h-12">
                        <div className="w-full h-full rounded-full bg-gray-200"></div>
                     </div>
                  </div>
               </div>
            </div>
            <div className="w-full flex justify-center sm:justify-end space-x-2">
               {imgSrc ? (
                  <Button variant="ghost">Farklı Resim Yükle</Button>
               ) : (
                  <Button variant="ghost" onClick={() => setOpen(false)}>
                     İptal et
                  </Button>
               )}
               <Button variant={"outline"} className="border-green-600">
                  Resmi uygula
               </Button>
            </div>
         </DialogContent>
      </Dialog>
   );
}

export default EditProfilePhotoDialog;

making esbuild treeshake with sideEffects:false

We have an Angular 18 application that used to be build with webpack. In our webpack.config.js file, we had this:

module.exports = (config, _options, targetOptions) => {
    config.module.rules = [
        {
            test: /.ts$/,
            /**
             * Declares all questionnaire ESM modules are safe to remove if completely unused.
             * This is tested to be relatively safe for the questionnaire project,
             * and adding new code that contains side effects should be avoided as much as possible.
             */
            sideEffects: false,
        },
        ...config.module.rules,
    ];

Now we moved to esbuild, and we want it to handle all files the same way – as they are of the nature sideEffects: false

How can I do that? I tried this way:

const sideEffectsPlugin = {
        name: 'sideEffects',
        setup(build) {
            build.onLoad({ filter: /.ts$/ }, async (args) => {
                const source = await require('fs').promises.readFile(
                    args.path,
                    'utf8',
                );
                return {
                    contents: source,
                    loader: 'ts',
                    sideEffects: false, // Set sideEffects to false for .ts files
                };
            });
        },
    };

But it does not seem to work.

Thanks.

Error with primordials not defined when running Node.js with Gulp and Angular CLI

I’m running Node.js version v22.12.0 and Gulp version CLI version: 3.0.0 and Local version: 5.0.0. When I try to run my project with Angular CLI, I encounter the following error:

fs.js:44
} = primordials;
    ^

ReferenceError: primordials is not defined
    at fs.js:44:5
    at req_ (C:UsersMyBook Hype AMDAppDataRoamingnpmnode_modulesangular-clinode_modulesnativesindex.js:143:24)
    at Object.req [as require] (C:UsersMyBook Hype AMDAppDataRoamingnpmnode_modulesangular-clinode_modulesnativesindex.js:55:10)
    at Object.<anonymous> (C:UsersMyBook Hype AMDAppDataRoamingnpmnode_modulesangular-clinode_modulesyamnode_modulesgraceful-fsfs.js:1:37)
    at Module._compile (node:internal/modules/cjs/loader:1565:14)
    at Object..js (node:internal/modules/cjs/loader:1708:10)
    at Module.load (node:internal/modules/cjs/loader:1318:32)
    at Function._load (node:internal/modules/cjs/loader:1128:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:219:24)

Node.js v22.12.0

Project Setup:

  • Node version: v22.12.0
  • Gulp CLI version: 3.0.0
  • Gulp local version: 5.0.0
  • Angular CLI version: 14.2.13

Gulp task runner is included in the project.

My package.json looks like this:

{
  "name": "deer-dialect-web",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.2.0",
    "@angular/common": "^14.2.0",
    "@angular/compiler": "^14.2.0",
    "@angular/core": "^14.2.0",
    "@angular/forms": "^14.2.0",
    "@angular/localize": "^14.3.0",
    "@angular/material": "^14.2.7",
    "@angular/material-moment-adapter": "^14.2.7",
    "@angular/platform-browser": "^14.2.0",
    "@angular/platform-browser-dynamic": "^14.2.0",
    "@angular/router": "^14.2.0",
    "@angular/youtube-player": "^13.3.9",
    "@ng-bootstrap/ng-bootstrap": "^13.1.1",
    "@ngx-translate/core": "^14.0.0",
    "@ngx-translate/http-loader": "^7.0.0",
    "bootstrap": "^5.3.3",
    "bootstrap-icons": "^1.10.0",
    "ngx-toastr": "^14.3.0",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.13",
    "@angular/cli": "~14.2.13",
    "@angular/compiler-cli": "^14.2.0",
    "@types/jasmine": "~4.0.0",
    "gulp": "^5.0.0",
    "jasmine-core": "~4.3.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.0.0",
    "typescript": "~4.7.2"
  }
}

{
  "name": "deer-dialect-web",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.2.0",
    "@angular/common": "^14.2.0",
    "@angular/compiler": "^14.2.0",
    "@angular/core": "^14.2.0",
    "@angular/forms": "^14.2.0",
    "@angular/localize": "^14.3.0",
    "@angular/material": "^14.2.7",
    "@angular/material-moment-adapter": "^14.2.7",
    "@angular/platform-browser": "^14.2.0",
    "@angular/platform-browser-dynamic": "^14.2.0",
    "@angular/router": "^14.2.0",
    "@angular/youtube-player": "^13.3.9",
    "@ng-bootstrap/ng-bootstrap": "^13.1.1",
    "@ngx-translate/core": "^14.0.0",
    "@ngx-translate/http-loader": "^7.0.0",
    "bootstrap": "^5.3.3",
    "bootstrap-icons": "^1.10.0",
    "ngx-toastr": "^14.3.0",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.13",
    "@angular/cli": "~14.2.13",
    "@angular/compiler-cli": "^14.2.0",
    "@types/jasmine": "~4.0.0",
    "gulp": "^5.0.0",
    "jasmine-core": "~4.3.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.0.0",
    "typescript": "~4.7.2"
  }
}

Steps I’ve Tried:

  • I have tried updating the dependencies and reinstalling them (npm
    install).
  • I have also tried downgrading the gulp version to 4.x but the error
    still persists.
  • I ensured that my Node.js version is compatible with the
    dependencies in the project.

Additional Information:

  • The error seems to be related to the primordials variable, which is
    not defined. It might be related to the graceful-fs package, which is
    used by angular-cli and gulp.
  • I am using Node.js v22.12.0, which could be a potential compatibility
    issue with older versions of the gulp or angular-cli tools.

Question:

How can I resolve the primordials is not defined error, especially considering my Node.js version? Do I need to downgrade my Node.js version or is there another fix?

Link from react-router-dom element not working as expected inside useDraggable from dnd-kit-core. Colliding onClick listener (maybe)

Here is the situation:

I did a kanban board using dnd-kit and I put a there a link element from React Router that when is clicked loads the entire page instead updating the element.

Already checked the following aspects:

  • Routes properly configured on App.tsx file
  • BrowserRouter as parent element on main.tsx file
  • Link element working behaviour out of the draggable element from dnd-core works as expected, which tells me that this is maybe an onClick crash between draggable element and Link element.

The following sources were consulted but didn’t clarify anything to me:

  1. https://community.auth0.com/t/page-is-refreshing-every-time-a-new-route-is-clicked-react-spa/66597
    –> I’m using “to” prop instead href.
  2. https://dev.to/alexanie_/link-component-in-react-router-3e83 –> I checked that reloadDocument is not set up.

Also the Link element works fine when I comment the {…listeners} part of my code.

This are the relevant parts of my code, any help is appreciated, also if you need aditional parts of my code I will be updating this question:

Draggable.tsx file:

interface DraggableUserProps {
  user: User;
}

const DraggableUser: React.FC<DraggableUserProps> = ({ user }) => {
  const { attributes, listeners, setNodeRef, transform } = useDraggable({
    id: user.id,
  });

  const style = {
    transform: `translate3d(${transform?.x}px, ${transform?.y}px, 0)`,
    border: "1px solid gray",
    borderRadius: "5px",
    padding: "10px",
    margin: "5px",
    backgroundColor: "white",
  };

  return (
    <div>
      <div
        ref={setNodeRef}
        style={style}
        {...listeners}
        {...attributes}
        onMouseEnter={(e) => {
          e.currentTarget.style.backgroundColor = "#8296a2";
          e.currentTarget
            .querySelectorAll("svg")
            .forEach((el: any) => (el.style.color = "white"));
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.backgroundColor = "white";
          e.currentTarget.querySelectorAll("svg").forEach((el: any) => {
            if (el.parentElement.className != "user-info") {
              el.style.color = "green";
            } else {
              el.style.color = "#8296a2";
            }
          });
          e.currentTarget.style.color = "black";
        }}
      >
        {/* Link element that works as expected */}
        <Link className="more-info" key={`useris${user.id}`} to="/user-details">
            <InfoIcon style={{ color: "#8296a2" }} className="user-info" />
        </Link>
        <div
          // onClick={(e) => e.stopPropagation()} Commented because didn't work
          style={{ display: "flex", justifyContent: "space-between" }}
        >
          <Link
            className="more-info"
            key={`useris${user.id}`}
            to="/user-details"
          >
            <InfoIcon style={{ color: "#8296a2" }} className="user-info" />
          </Link>
          {user.name}{" "}
          <a
            href={`https://wa.me/${user.phone}?text=${user.message.replace(
              " ",
              "%20"
            )}`}
          >
            <WhatsApp
              style={{ color: "green" }}
              onMouseEnter={(e) =>
                (e.currentTarget.style.transform = "scale(1.5)")
              }
              onMouseLeave={(e) =>
                (e.currentTarget.style.transform = "scale(1)")
              }
            />
          </a>
        </div>
      </div>
    </div>
  );
};

export default DraggableUser;

App.tsx file:

import React from "react";
import "bootstrap/dist/css/bootstrap.css";
import { Routes, Route } from "react-router-dom";
// import Routes from "./Routes.tsx"; Ver como importar
import "./App.css";
import ResponsiveAppBar from "./components/General/ResponsiveAppBar";
import myRoutes from "./components/api/myroutes";
import ProtectedRoute from "./components/api/protectedRoute";
import UserDetails from "./components/parts/crm/UserDetails";

function App() {
  return (
    <>
      <ResponsiveAppBar myItems={myRoutes} />
      <Routes>
        {myRoutes
          // .filter((elmnt) => elmnt.path !== "/user-details/:id")
          .map((elmnt) =>
            elmnt.protected ? (
              <Route
                key={elmnt.path}
                path={elmnt.path}
                element={<ProtectedRoute element={elmnt.element} />}
              />
            ) : (
              <Route
                key={elmnt.path}
                path={elmnt.path}
                element={elmnt.element}
              />
            )
          )}
        {/* <Route path="/user-details" element={<UserDetails />} /> */}
      </Routes>
    </>
  );
}

export default App;

Main.tsx file:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import { BrowserRouter } from "react-router-dom";
import { AuthProvider } from './components/General/AuthProvider';

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <AuthProvider>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </AuthProvider>
  </React.StrictMode>
);

I would like to know if there is a way in which listeners from React Router Link element and dnd-kit useDraggable wouldn’t collide.

onClick={(e) => e.stopPropagation()}

didn’t work.

Thanks in advance guys.

Variable becomes undefined when I link its class as a script

I am using javascript and have a map generation class called generate.js,which whenever I link as a script to any HTML file I get the error Uncaught (in promise) ReferenceError: scl is not defined. From what I can see scl is defined normally, this is especially a problem because I need generate.js for a crucial feature in my website, if you can find what is causing scl to become undefined or how to solve it, I would appreciate it.

Below is the code for generate.js, map_display.html from which the values are defined, and load.html which includes the feature I was talking about(a JSON loader)

let cols, rows;
let terrain = [];

let generating = false;

function setup() {
  createCanvas(width, height);
  background(200);
  noiseDetail(10,0.5);
  cols = width / scl;
  rows = height / scl;
  noiseSeed(seed);

  for (let x = 0; x < cols; x++) {
    terrain[x] = [];  
    for (let y = 0; y < rows; y++) {
      terrain[x][y] = 0;
    }
  }
}

function generateTerrain() {
  let yoff = 0;
  for (let y = 0; y < rows; y++) {
    let xoff = 0;
    for (let x = 0; x < cols; x++) {
      let noiseValue = noise(xoff / zoomFactor,yoff / zoomFactor);
      terrain[x][y] = noiseValue;
      xoff += noiseScale;
    }
    yoff += noiseScale;
  }
}

function draw() {
  if (generating) {
    generateTerrain();
    loadPixels();
    
    for (let y = 0; y < rows; y++) {
      for (let x = 0; x < cols; x++) {
        let val = terrain[x][y];
        let colorVal = getColor(val);
        
        fill(colorVal);
        noStroke();
        rect(x * scl, y * scl, scl, scl);
      }
    }
    noLoop();
    generating = false;
  }
}

function getColor(val) {
  let c1, c2;

  if (val < 0.35) {
    c1 = color(0, 0, 255); 
    c2 = color(0, 0, 180); 
    val = map(val, 0, 0.3, 0, 1);
  } else if (val < 0.45) {
    c1 = color(244, 164, 96); 
    c2 = color(255, 204, 153);
    val = map(val, 0.3, 0.4, 0, 1);
  } else if (val < 0.7) {
    c1 = color(34, 139, 34);
    c2 = color(0, 100, 0);
    val = map(val, 0.4, 0.7, 0, 1);
  } else {
    c1 = color(139, 69, 19); 
    c2 = color(205, 133, 63);
    val = map(val, 0.7, 1, 0, 1);
  }
  return lerpColor(c1, c2, val);
}

function generateMap() {
  let width = parseInt(document.getElementById('width').value);
  let height = parseInt(document.getElementById('height').value);
  let scl = parseInt(document.getElementById('scl').value);
  let noiseScale = parseFloat(document.getElementById('noiseScale').value);
  let zoomFactor = parseFloat(document.getElementById('zoomFactor').value);
  let seed = parseInt(document.getElementById('seed').value);
  if(!seed){
    seed = Math.floor(Math.random()*10000);
  }

  let url = `map_display?width=${width}&height=${height}&scl=${scl}&noiseScale=${noiseScale}&zoomFactor=${zoomFactor}&seed=${seed}`;

  window.location.href = url;
}
<!DOCTYPE html>
<html>
  <head>
    <title>Perlin Noise Terrain</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <h1>Fuming's Generator</h1>

    <nav class="navbar">
        <ul>
          <li><a href="/">Home</a></li>
          <li><a href="/map">Perlin Map Generator</a></li>
          <li><a href="/load">Load Downloaded Map</a></li>
          <li><a href="/about">About</a></li>
          <li><a href="/map">Map list</a></li>
        </ul>
    </nav>
     <script>
        const searchParams = new URLSearchParams(window.location.search);

        let width = parseInt(searchParams.get('width'));
        let height = parseInt(searchParams.get('height'));
        let scl = parseInt(searchParams.get('scl'));
        let noiseScale = parseFloat(searchParams.get('noiseScale'));
        let zoomFactor = parseFloat(searchParams.get('zoomFactor'));
        let seed = parseInt(searchParams.get('seed'));
    </script>
    <script src="/generate.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.min.js"></script>

    <script>
       generating = true;
    </script>

    <div class="content">
       <button onclick="saveSettings(width,height,scl,noiseScale,zoomFactor,seed)">Save Settings</button>
    </div>
    <script src="/save.js"></script>
  </body>
</html>
body{
    margin:0;
    padding:0;
}

h1{
    text-align:center;
    color:white;
    background-color:black;
    width:100%;
    padding:20px;
    box-sizing:border-box;
    margin:0;
    position:fixed;
    top:0;
    left:0;
    height:70px;
    z-index: 1000;
}

.content{
    margin-left: 220px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.content h2{
    text-align: center;
    font-size: 30px;
    margin-bottom: 20px;
    color: #333;
}

.navbar{
    width: 200px;
    height: calc(100vh-70px);
    background-color: lightgray;
    position: fixed;
    top: 70px;
    left: 0;
    bottom:0;
    padding: 0;
    margin: 0;
    overflow-y:auto;
    z-index: 999;
}
.navbar ul{
    list-style-type:none;
    background-color:lightgray;
    padding: 0px;
    margin: 0px;
}
.navbar a{
    display:block;
    padding:10px;
    width:100%;
    padding:10px;
    box-sizing:border-box;
    text-decoration:none;
}
.navbar a:hover{
    background-color:#b5b5b5;
}

.content {
    margin-left: 220px;
    padding: 20px;
    margin-top:60px;
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Load Map Settings</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Load Map Settings</h1>

    <nav class="navbar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/map">Perlin Map Generator</a></li>
            <li><a href="/load">Load Downloaded Map</a></li>
            <li><a href="/about">About</a></li>
        </ul>
    </nav>

    <div class="content">
        <input type="file" id="load-json" accept=".json">
        <p>Choose a JSON file with the saved map settings to load and generate the map.</p>
    </div>

    <script>
            document.getElementById('load-json').addEventListener('change', function(event) {
          const file = event.target.files[0];
          if (file) {
             const reader = new FileReader();
              reader.onload = function(e) {
                 const jsonData = JSON.parse(e.target.result);
                 width = jsonData.width;
                 height = jsonData.height;
                 scl = jsonData.scl;
                 noiseScale = jsonData.noiseScale;
                 zoomFactor = jsonData.zoomFactor;
                 seed = jsonData.seed;
                 console.log(width,height,scl,noiseScale,zoomFactor,seed);
          };
          reader.readAsText(file);
             }
        });

        generating = true;
        
    </script>
    <script src="generate.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
</body>
</html>

Component state reset and UI tree with different JSX syntax

I am referring to examples on this page and it is pertaining to React preserving state based on different conditions specific to the UI tree.

Specifically, is there any difference in the way React sees the below being rendered dynamically from a UI tree perspective?

  • Option 1:

    return (
      <div>
        {isPlayerA ? (
          <Counter person="Taylor" />
        ) : (
          <Counter person="Sarah" />
        )}
      </div>
    );
    
  • Option 2:

    return (
      <div>
        {isPlayerA && <Counter person="Taylor" />}
        {!isPlayerA && <Counter person="Sarah" />}
      </div>
    );