useSearchParams() should be wrapped in a suspense boundary at page “/find/searchResults”

Ive tried wrapping my code in Suspense Tags but Im still getting the following error while building production build of my nextjs app.

 ⨯ useSearchParams() should be wrapped in a suspense boundary at page "/find/searchResults". Read more: https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
    at a (/home/yash/nextjs-hireme/hireme/.next/server/chunks/244.js:1:6747)
    at f (/home/yash/nextjs-hireme/hireme/.next/server/chunks/244.js:1:23270)
    at h (/home/yash/nextjs-hireme/hireme/.next/server/app/find/searchResults/page.js:1:3734)
    at nO (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:45959)
    at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:47734)
    at nL (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:65533)
    at nN (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:63164)
    at n$ (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:46311)
    at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:47780)
    at nI (/home/yash/nextjs-hireme/hireme/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:20:62515)
Error occurred prerendering page "/find/searchResults". Read more: https://nextjs.org/docs/messages/prerender-error
Export encountered an error on /find/searchResults/page: /find/searchResults, exiting the build.
 ⨯ Static worker exited with code: 1 and signal: null

Ive also tried reinstalling the dependencies but nothing works.
This page displays the search results fetched by the search-services component.
Here’s my folder structure:

app/
├── components/
|      ├── search-services.jsx 
|
├── find/
│     ├── searchResults/
│     |         ├── page.jsx
│     ├── page.jsx

Here’s my code:

"use client";

import React, { useEffect, useState, Suspense } from "react";
import { useSearchParams } from "next/navigation";
import searchServices from "../../components/search-services";
import Link from "next/link";
import ServiceDetails from "../../components/service-details";
import { auth, db } from "../../firebase/config";
import { doc, getDoc } from "firebase/firestore";
import calculateDistance from "../../components/calculate-distance";

const SearchResults = () => {
  const searchParams = useSearchParams();
  const searchTerm = searchParams.get("query").trim() || "";
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selectedService, setSelectedService] = useState(null);
  const [userLocation, setUserLocation] = useState(null);

  const handleServiceClick = (service) => setSelectedService(service);
  const handleCloseDetails = () => setSelectedService(null);

  // Fetch user location from Firestore
  useEffect(() => {
    const fetchUserLocation = async () => {
      auth.onAuthStateChanged(async (user) => {
        if (user) {
          const docRef = doc(db, "Users", user.uid);
          const docSnap = await getDoc(docRef);
          if (docSnap.exists()) {
            const userData = docSnap.data();
            if (userData.location) {
              setUserLocation(userData.location); // Assume location is { latitude, longitude }
            }
          }
        } else {
          console.log("User is not logged in");
        }
      });
    };

    fetchUserLocation();
  }, []);

  // Fetch search results
  useEffect(() => {

    const fetchResults = async () => {
      if (!searchTerm) return;
      setLoading(true);
      try {
        const services = await searchServices(searchTerm);
        setResults(services);
      } catch (error) {
        console.error("Error fetching search results:", error);
      }
      setLoading(false);
    };

    fetchResults();

  }, [searchTerm]);

  return (
    <Suspense>
      <div className="min-h-screen bg-gray-50 px-4 py-6">
        <h1 className="text-2xl font-semibold mb-4">Search Results for "{searchTerm}"</h1>
        <Link href="/find" className="text-teal-600 mt-4 inline-block">
          ← Back to Search
        </Link>
    
        {loading ? (
          <p>Loading...</p>
        ) : results.length === 0 ? (
          <p className="text-gray-500">No services found.</p>
        ) : (
          <div className="grid grid-cols-1 gap-4">
          {results.map((service) => {
            const distance = userLocation && service.location 
              ? calculateDistance(userLocation, service.location) 
              : null;
            return (
              <div key={service.id} className="relative p-4 border rounded-lg cursor-pointer hover:bg-gray-50 transition-colors shadow-sm" onClick={(e) => {
                e.stopPropagation();
                handleServiceClick(service);
              }}>
                <div className="flex justify-between items-center">
                  <h2 className="text-lg font-semibold text-gray-800">{service.title}</h2>
                </div>
                <p className="text-gray-600 mt-2 line-clamp-2">{service.description}</p>
                <div className="mt-2">
                  <div className="flex justify-between">
                    <div>
                      <p className="text-sm text-gray-500">Provider: {service.providerName}</p>
                      <p className="text-sm text-gray-500">Phone: {service.providerPhone}</p>
                      <p className="text-sm text-gray-500">Email: {service.providerEmail}</p>
                    </div>
                    {distance !== null && (
                      <div className="text-right">
                        <span className="text-md font-bold text-blue-700">
                          {distance.toFixed(2)} km
                        </span>
                      </div>
                    )}
                  </div>
                </div>
                <div className="mt-4 flex justify-between items-center">
                  <p className="text-teal-600 font-bold mb-2">
                    ₹{parseFloat(service.price.min).toFixed(2)} - ₹{parseFloat(service.price.max).toFixed(2)}
                  </p>
                  <span className="text-sm text-gray-500">{new Date(service.timestamp).toLocaleDateString('en-GB')}</span>
                </div>
              </div>
            );
          })}
        </div>
        )}
  
        {/* Display selected service details */}
        {selectedService && (
          <ServiceDetails
            key={selectedService.userId}
            userId={selectedService.userId}
            service={selectedService}
            onClose={handleCloseDetails}
          />
        )}
      </div>
    </Suspense>
  );
};

export default SearchResults;

I am running Next.js 15.1.6

Need help to create a success message

So I am trying to create a project – RSS reader and I have a problem.
After I adding new RSS Feed I dont have a message under url input about succsefull rss load.

I tried everything and I cant find a problem. Can someone help me with this problem please?

I don’t really know how to fix it and I need a help

app.js:

import i18next from 'i18next';
import { initView } from './view.js';
import { createSchema } from './validate.js';
import { fetchRss } from './rss.js';
import { parseRSS } from './parser.js';
import { checkForUpdates } from './updater.js';

export default () => {
  const state = {
    urls: [],
    isValid: true,
    error: '',
    feeds: [],
    posts: [],
    readPostIds: [],
    loading: false,
  };

  i18next.init({
    lng: 'ru',
    resources: {
      ru: {
        translation: {
          success: 'RSS успешно загружен',
          invalidUrl: 'Ссылка должна быть валидным URL',
          existingUrl: 'RSS уже существует',
          required: 'Не должно быть пустым',
          networkError: 'Ошибка сети',
          invalidRSS: 'Ресурс не содержит валидный RSS',
        },
      },
    },
  });

  const watchedState = initView(state, i18next);

  const form = document.querySelector('.rss-form');
  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    const url = formData.get('url').trim();

    const schema = createSchema(watchedState.urls);

    try {
      if (watchedState.urls.includes(url)) {
        throw new Error('existingUrl');
      }

      await schema.validate(url);
      watchedState.loading = true;

      const rssData = await fetchRss(url);

      const { feed, posts } = parseRSS(rssData);

      watchedState.feeds.push(feed);
      watchedState.posts.push(...posts.map((post, index) => ({
        ...post,
        id: `post-${index}`,
      })));
      watchedState.urls.push(url);

      watchedState.isValid = true;
      watchedState.error = '';

      watchedState.feeds = [...watchedState.feeds];
      watchedState.posts = [...watchedState.posts];
      watchedState.urls = [...watchedState.urls];

      if (watchedState.urls.length === 1 && !watchedState.loading) {
        setTimeout(() => checkForUpdates(watchedState), 1000);
      }

    } catch (err) {
      if (err.name === 'ValidationError') {
        watchedState.error = err.message;
      } else {
        watchedState.error = i18next.t(err.message);
      }
      watchedState.isValid = false;
    } finally {
      watchedState.loading = false;
    }
  });
};

view.js

import onChange from 'on-change';
import { Modal } from 'bootstrap';
export const initView = (state, i18next) => {
  const input = document.querySelector('#url-input');
  const feedback = document.querySelector('.feedback');
  const feedsContainer = document.querySelector('.feeds');
  const postsContainer = document.querySelector('.posts');

  const modalTitle = document.querySelector('.modal-title');
  const modalBody = document.querySelector('.modal-body');
  const fullArticleLink = document.querySelector('.full-article');
  const modalElement = document.getElementById('modal');
  const modal = new Modal(modalElement);

  const handlePostClick = (post) => {
    if (!post.title || !post.description || !post.link) {
      return;
    }

    modalTitle.textContent = post.title;
    modalBody.innerHTML = post.description;
    fullArticleLink.href = post.link;
    modal.show();
  };

  const renderFeeds = () => {
    feedsContainer.innerHTML = `
      <h4 class="${state.feeds.length === 0 ? 'd-none' : ''} mb-4">Фиды</h4>
      ${state.feeds.map((feed) => `
        <div class="feed mb-4">
          <h6>${feed.title}</h6>
          <p>${feed.description}</p>
        </div>
      `).join('')}
    `;
  };

  const renderPosts = () => {
    postsContainer.innerHTML = `
      <h4 class="${state.posts.length === 0 ? 'd-none' : ''} mb-4">Посты</h4>
      ${state.posts.map((post) => `
        <div class="post mb-3 d-flex justify-content-between align-items-center">
          <a href="${post.link}" target="_blank" class="post-link ${state.readPostIds.includes(post.id) ? 'text-secondary fw-normal' : 'fw-bold'}" data-post-id="${post.id}">
            ${post.title}
          </a>
          <button class="btn btn-outline-primary btn-sm" data-post-id="${post.id}">Просмотр</button>
        </div>
      `).join('')}
    `;

    document.querySelectorAll('.post-link').forEach((link) => {
      link.addEventListener('click', (e) => {
        const postId = e.target.dataset.postId;
        if (postId && !state.readPostIds.includes(postId)) {
          state.readPostIds.push(postId);
          e.target.classList.add('text-muted', 'fw-normal');
          e.target.classList.remove('fw-bold')
        }
      });
    });

    document.querySelectorAll('.btn-outline-primary').forEach((button) => {
      button.addEventListener('click', (e) => {
        e.preventDefault();
        const postId = e.target.dataset.postId;
        const post = state.posts.find((p) => p.id === postId);
        if (post) {
          handlePostClick(post);
          if (!state.readPostIds.includes(postId)) {
            state.readPostIds.push(postId);
            const postLink = document.querySelector(`.post-link[data-post-id="${postId}"]`)
            if (postLink) {
              postLink.classList.add('text-muted', 'fw-normal');
              postLink.classList.remove('fw-bold')
            }
          }
        }
      });
    });
  };

  return onChange(state, (path) => {
    if (path === 'isValid' || path === 'error') {
      if (state.isValid) {
        feedback.textContent = i18next.t('success');
        feedback.classList.replace('text-danger', 'text-success');
        input.classList.remove('is-invalid');
        input.value = '';
        input.focus();
      } else {
        feedback.textContent = i18next.t(state.error);
        feedback.classList.replace('text-success', 'text-danger');
        input.classList.add('is-invalid');
      }
    }

    if (path === 'feeds') {
      renderFeeds();
    }

    if (path === 'posts' || path === 'readPostIds') {
      renderPosts();
    }
  });
};

updater.js

import { fetchRss } from "./rss.js";
import { parseRSS } from "./parser.js"

export const checkForUpdates = async (state) => {
    try {
        for (const url of state.urls) {
            const rssData = await fetchRss(url);
            const { posts: newPosts } = parseRSS(rssData)
            
            const existingUrl = state.posts.map((post) => post.link);
            const uniqueNewPosts = newPosts.filter(
                (post) => !existingUrl.includes(post.link)
            );

            if (uniqueNewPosts.length > 0) {
                state.posts.unshift(...uniqueNewPosts);
            }
        }
    } catch (err) {
        console.log('Error', err);
    } finally {
        setTimeout(() => checkForUpdates(state), 5000)
    }
}

I tried to change state

How do I (make tooltipster) take over an existing or future eventlistener in javascript?

I use tooltipster to make tooltips on my site.

When hovering elements they display the content in a bubble.

On touch devices however..

..the tooltips shows on a tap since there is no hover. But a tap like a click triggers links etc. I go around this by making tooltipster take over the href of the element and display it inside the tooltip on a ad hoc created element like “Click here for more detail”.
That works without a problem.

Now what about js click events?

I have elements on the site without href or <a> made by js addeventlistener. This is sometimes done before tooltipster is activated in js and sometimes after and sometimes even with ajax.
So, just like taking over the click/tap by href before, how do I make tooltipster take over the eventlistener?

More genreal question

This is not necessarily tooltipster specific. I can do that part. The question is rather, how to transfer eventlisteners in the first place?


Do I set a certain class on these elements and put the eventlisteners in a js Map? If so, then how do I transfer it to an element inside the tooltip without losing its target?

Or maybe this is just wrong coding, like the wrong approach in the first place? Maybe the question is wrong and I need another approach?

All help really appreciated!

There is code below, but it’s not necessarily relevant:

isTouch = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)
$('.tooltip' + (isTouch?':not(.ajx)':''))
.tooltipster({
    debug:true,
    animation: 'grow',
    interactive:true,
    repositionOnScroll:true,
    contentAsHTML : true,
    //trackOrigin:true,     //performance!
    delay: 200,
    trigger: 'custom',
    triggerOpen: {
        click: true,
        mouseenter: true,
        tap: true
    },
    triggerClose: {
        mouseleave: true,
        click: true,
        tap: true
    }
})  
/***** Don't open tooltips of parents  ****/
//click (parent events comes after child)
.has('.tooltip')
    .tooltipster('option' , 'functionBefore' ,  (inst, helper) => {     //console.log('functionBefore', helper)
        if (helper.event && !helper.event.target?.isEqualNode(helper.origin))
            return false;//console.log(helper.event)//.stop()
    })
//hover (child events comes after parent)
.children('.tooltip')
    .tooltipster('option' , 'functionBefore' ,  (inst, helper) => {     //console.log('functionBefore', helper)
        $(helper.origin).parents('.tooltip').tooltipster('close')
    })
    .tooltipster('option' , 'functionAfter' ,  (inst, helper) => {      //console.log('functionAfter', helper)
        //If hover out on or via parent 
        if (helper.event.relatedTarget?.classList.contains('tooltip'))
            $(helper.event.relatedTarget).tooltipster('open')
    })

localStorage.getItem data is showing up as null

I am making A constructor function called LocalDataStore for my game/physics engine. The purpose Is to make It much simpler to use Javascript’s localStorage system.

Everything works fine until I try to get and parse the data then push It into my ParsedData Array(which Is just A global array to hold the data).

The data shows up as null In the ParsedData Array and In localStorage there Is no data at all.
If anyone can lead me In the right direction or can tell me what they think Is Wrong That would be great, Thank you.

(If you want to test this yourself just make two HTML documents + two JS files, Than make a third JS file called library then paste my Code that I posted here. Use one of your HTML docs to add and then set data into localStorage using my LocalDataStore Class. Than use the second HTML doc to get the data. look in your console to see if you were able to successfully get the data from the first document)

//-----------------------//
let LocalData  = new Array(); // local game/player data Array which is used for the LocalDataStore system.
let ParsedData = new Array(); // LocalData is sent here after it is parsed using 'LocalDataStore.get()'.
//-----------------------//

/**********************************************
* You can 'set' data in one html file then access it in another using 'get'.
* 
* LocalDataStore.set('key') to set a key name for the data.
*
* LocalDataStore.get('key') to access the data using the key name.
*
* LocalDataStore.add('myData') to add data to the LocalData Array.
*
* LocalDataStore.clear() clears all data.
*
* LocalDataStore.remove('key') to remove specific data.
**********************************************/

let LocalDataStore = function(){ 
    // add data to the LocalData Array.
    this.add = function(data){ 
        LocalData.push(data);
        
        console.log("New Data has been added to the 'LocalData' Array");
    };

    this.set = function(key){ 
        // maybe I should clear localStorage here?
        localStorage.clear();
        
        // set a key name for your data in the LocalData Array.
        localStorage.setItem(key, JSON.stringify(LocalData));

        if(LocalData[0] == null || LocalData[0] == undefined){
            console.log("[error@ 'LocalData']: 'no data has been found.'")
        }

        console.log("'LocalData' has been set with the key name: ["+key+"]");
    };

    this.get = function(key){ 
        // retrieve your data from LocalData and parse & add it to the ParsedData Array.
        let userData = JSON.parse(localStorage.getItem(key));

        ParsedData.push(userData);

        console.log("[parsed-data: "+userData+"]");

        if(ParsedData[0] == null || ParsedData[0] == undefined){
            console.log("[error@ 'ParsedData']: 'data-parsing failed or no data has been found.'")
        }

        console.log("Accessed & Parsed 'LocalData' with the key name: ["+key+"].");
        console.log("New Data has been Added to the 'ParsedData' Array.");
    };

    this.remove = function(key){ 
        // remove specific data from localStorage.
        localStorage.removeItem(key)
    };

    this.clear = function(){ 
        // clear all data from localStorage.
        localStorage.clear();
    };
};

This Is the Console Output from the first HTML doc:

New Data has been added to the 'LocalData' Array
'LocalData' has been set with the key name: [pd1]
localStorage
Storage {pd1: '[5]', length: 1}

This Is the Console Output from the second HTML doc:

[parsed-data: null]
[error@ 'ParsedData']: 'data-parsing failed or no data has been found.'
Accessed & Parsed 'LocalData' with the key name: [pd1].
New Data has been Added to the 'ParsedData' Array.

Entering data into a text field on a website

I’m looking for a way to enter a one-time code into the https://login.microsoftonline.com/common/oauth2/deviceauth page in the ‘Kod’ field

So far I’ve only managed to stop the cursor from blinking but the code is still not visible in the www page field. I’ve used JavaScript and I’m wondering if this is the right approach. I’m using the **TEdgeBrowser **control and in **DevTools **in the **Console **tab there are no logs from the attempt to enter data. The field does not appear to be framed so this problem is gone. I enter the script in the ‘EdgeBrowser1FrameNavigationCompleted’ event

String javascriptCode =

      "setTimeout(function() { "
        "  console.log('Sprawdzanie pola input[name=otc]...');"
        "  var input = document.querySelector('input[name=otc]'); "
        "  if (input) { "
        "    console.log('Pole OTC znalezione! Wprowadzam kod...');"
        "    input.value = '12345'; "
        "    input.dispatchEvent(new Event('input', { bubbles: true })); "
        "  } else { "
        "    console.log('Błąd: Nie znaleziono pola OTC!');"
        "  } "
        "}, 2000);";

EdgeBrowser1->ExecuteScript(javascriptCode);

I am getting a react webpack error when I try to import a function

I am working on a website using MERN stack and I need to implement a function to run when I click a button. I already did the function but whenever I try to import and use it in a react page, I just get an error and I genuinely have no idea why. The function works when I run it in it’s own file.

populate.js:

import xlsxpopulate from 'xlsx-populate';

function calculateInterest(price, interestRate) {
    return (price * interestRate) / 3000;
}

console.log(calculateInterest(809055, 0.5));

function addMonth(dateStr, count) {
    let [day, month, year] = dateStr.split('/').map(Number);

    let date = new Date(year, month - 1, day);

    date.setMonth(date.getMonth() + count);

    let newDay = date.getDate().toString().padStart(2, '0');
    let newMonth = (date.getMonth() + 1).toString().padStart(2, '0');
    let newYear = date.getFullYear();

    return `${newDay}/${newMonth}/${newYear}`;
}

let a = 0;

function dateDifference(dateStr1, dateStr2) {
    let [day1, month1, year1] = dateStr1.split('/').map(Number);
    let [day2, month2, year2] = dateStr2.split('/').map(Number);

    let date1 = new Date(year1, month1 - 1, day1);
    let date2 = new Date(year2, month2 - 1, day2);

    let diffTime = Math.abs(date2 - date1);

    return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}

let originalPrice = 0;

export function populateExcelForMonthly(
    paymentDate,
    price,
    monthlyPayment,
    interestRate
) {
    const monthCount = Math.floor(price / monthlyPayment);

    originalPrice = price;
    let paymentLeft = price;
    let _paymentLeft = price;
    let _paymentDate = paymentDate;
    let currentInterest = 0;
    let totalInterest = 0;
    const currentDate = new Date();
    let day = currentDate.getDate();
    let month = currentDate.getMonth() + 1;
    let year = currentDate.getFullYear();
    let formattedCurrentDate = `${day.toString().padStart(2, '0')}/${month
        .toString()
        .padStart(2, '0')}/${year}`;
    let previousDate = formattedCurrentDate;

    let i;

    xlsxpopulate.fromFileAsync('./src/util/template.xlsx').then((workbook) => {
        for (i = 0; i < monthCount; i++) {
            // Aylık Ödeme Tarihi
            workbook
                .sheet('Sheet1')
                .cell(`B${5 + i}`)
                .value(_paymentDate);

            // Aylık Ödenicek Miktar (Ana para bitene kadar sabit)
            workbook
                .sheet('Sheet1')
                .cell(`C${5 + i}`)
                .value(monthlyPayment);

            currentInterest =
                calculateInterest(_paymentLeft, interestRate) *
                dateDifference(previousDate, _paymentDate);

            _paymentLeft -= monthlyPayment;
            _paymentLeft = _paymentLeft + currentInterest;
            // Ödenmesi Gereken Paranın Geri Kalanı
            workbook
                .sheet('Sheet1')
                .cell(`D${5 + i}`)
                .value(_paymentLeft);

            // Vade Farkı
            workbook
                .sheet('Sheet1')
                .cell(`E${5 + i}`)
                .value(currentInterest);

            paymentLeft -= monthlyPayment;
            paymentLeft += currentInterest;

            currentInterest = 0;

            // Önceki tarihten ödeme tarihine kadar olan mesafe
            workbook
                .sheet('Sheet1')
                .cell(`F${5 + i}`)
                .value(dateDifference(previousDate, _paymentDate));

            previousDate = _paymentDate;
            _paymentDate = addMonth(_paymentDate, 1);
        }

        workbook
            .sheet('Sheet1')
            .cell(`B${5 + i}`)
            .value(_paymentDate);

        workbook
            .sheet('Sheet1')
            .cell(`C${5 + i}`)
            .value(paymentLeft);

        workbook
            .sheet('Sheet1')
            .cell(`D${5 + i}`)
            .value('0,00');

        currentInterest =
            calculateInterest(_paymentLeft, interestRate) *
            dateDifference(previousDate, _paymentDate);
        workbook
            .sheet('Sheet1')
            .cell(`E${5 + i}`)
            .value(currentInterest);

        totalInterest += currentInterest;
        workbook
            .sheet('Sheet1')
            .cell(`F${5 + i}`)
            .value(dateDifference(previousDate, _paymentDate));

        workbook
            .sheet('Sheet1')
            .cell(`B${6 + i}`)
            .value('Toplam Ödeme');

        workbook
            .sheet('Sheet1')
            .cell(`B${7 + i}`)
            .value('Toplam Vade Farkı');

        workbook
            .sheet('Sheet1')
            .cell(`C${6 + i}`)
            .value(originalPrice + paymentLeft);

        originalPrice = 0;
        totalInterest = 0;

        workbook
            .sheet('Sheet1')
            .cell(`C${7 + i}`)
            .value(paymentLeft);

        return workbook.toFileAsync('./src/util/outputs/output.xlsx');
    });
}

The react page I am trying to import the function in:

import React, { useState } from 'react';

//import PaymentForm from '../components/PaymentForm';
import { PaymentSetup } from '../components/PaymentSetup';
import { PaymentStructure } from '../components/PaymentStructure';
import { populateExcelForMonthly } from '../hooks/populate';
import { useMultistepForm } from '../hooks/useMultistepForm';

const Create = () => {
    const INITIAL_DATA = {
        title: '',
        startDate: '',
        currency: '',
        price: 0,
        interestRate: 0,
        paymentType: '',
        monthlyPayment: 0,
    };

    const [data, setData] = useState(INITIAL_DATA);

    function updateFields(fields) {
        setData((prev) => {
            return { ...prev, ...fields };
        });
    }

    const {
        steps,
        currentStepIndex,
        step,
        isFirstStep,
        previous,
        next,
        isLastStep,
    } = useMultistepForm([
        <PaymentSetup {...data} updateFields={updateFields} />,
        <PaymentStructure {...data} updateFields={updateFields} />,
    ]);

    async function onSubmit(e) {
        e.preventDefault();

        if (isLastStep) {
            const payment = {
                title: data.title,
                monthlyPayment: data.monthlyPayment,
                startDate: data.startDate,
                currency: data.currency,
                price: data.price,
                interestRate: data.interestRate,
                paymentType: data.payment,
            };
            const response = await fetch('/api/payments', {
                method: 'POST',
                body: JSON.stringify(payment),
                headers: {
                    'Content-Type': 'application/json',
                },
            });
            const json = await response.json();

            if (response.ok) {
                INITIAL_DATA.title = '';
                INITIAL_DATA.startDate = '';
                INITIAL_DATA.currency = '';
                INITIAL_DATA.price = 0;
                INITIAL_DATA.interestRate = 0;
                INITIAL_DATA.paymentType = '';
                INITIAL_DATA.monthlyPayment = 0;
                console.log('Yeni sözleşme eklendi:', json);
            }
        } else {
            next();
        }
    }

    // Multi-step Form
    return (
        <div className="create-container">
            <form className="form-container" onSubmit={onSubmit}>
                <div className="create-step">
                    {currentStepIndex + 1} / {steps.length}
                </div>
                {step}
                <div className="create-context">
                    {!isFirstStep && (
                        <button type="button" onClick={previous}>
                            Geri
                        </button>
                    )}
                    {isLastStep ? (
                        <button
                        onClick={populateExcelForMonthly(
                                INITIAL_DATA.startDate,
                                INITIAL_DATA.price,
                                INITIAL_DATA.monthlyPayment,
                                INITIAL_DATA.interestRate
                            )}
                        >
                            Bitir
                        </button>
                    ) : (
                        <button>İleri</button>
                    )}
                </div>
            </form>
        </div>
    );
};

export default Create;

error:

Failed to compile.

Module not found: Error: Can't resolve 'buffer' in '/home/canakil/Code/cemil-mern/frontend/node_modules/safe-buffer'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "buffer": require.resolve("buffer/") }'
        - install 'buffer'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "buffer": false }
WARNING in ./node_modules/sax/lib/sax.js 139:13-37
Module not found: Error: Can't resolve 'stream' in '/home/canakil/Code/cemil-mern/frontend/node_modules/sax/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
        - install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "stream": false }

WARNING in [eslint]
src/pages/Create.js
  Line 6:10:  'populateExcelForMonthly' is defined but never used  no-unused-vars

ERROR in ./node_modules/safe-buffer/index.js 3:13-30
Module not found: Error: Can't resolve 'buffer' in '/home/canakil/Code/cemil-mern/frontend/node_modules/safe-buffer'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "buffer": require.resolve("buffer/") }'
        - install 'buffer'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "buffer": false }

ERROR in ./node_modules/xlsx-populate/lib/Encryptor.js 12:15-32
Module not found: Error: Can't resolve 'crypto' in '/home/canakil/Code/cemil-mern/frontend/node_modules/xlsx-populate/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
        - install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "crypto": false }

ERROR in ./node_modules/xlsx-populate/lib/Workbook.js 4:11-24
Module not found: Error: Can't resolve 'fs' in '/home/canakil/Code/cemil-mern/frontend/node_modules/xlsx-populate/lib'

webpack compiled with 3 errors and 2 warnings

I would appreciate any direction on why I’m getting this error and what it means.

Javascript Drive API nextPageToken never changes

I am trying to build a Chrome Extension using the Drive API. I believe I have it working mostly but I keep getting the same nextPageToken on recursive calls. I want to be able to list all the file’s ids by checking if nextPageToken exists after each fetch.

I am doing a simple version of it initially by using a counter (ctr) in a do loop. The
returned data from the fetch always has the same nextPageToken value, per the last 2 lines of code below.

let morePagesAvailable = '';
let initVal; //oauth2 initialization
let url = new URL('https://www.googleapis.com/drive/v3/files?fields=nextPageToken,files(id)&pageToken=');
let params = url.searchParams;

//onLoad
window.onload = function () {
      document.querySelector('button').addEventListener('click', function () {
            chrome.identity.getAuthToken({ interactive: true }, function (token) {
                  init = {
                        method: 'GET',
                        async: true,
                        headers: {
                              Authorization: 'Bearer ' + token,
                              'Content-Type': 'application/json'
                        },
                        'contentType': 'json'
                  };
                  fetchIt(init);
            });
      })
};

//Fetch data
async function fetchIt(initVal) {
      let ctr = 1;
      do {
            params.delete('pageToken');
            params.append('pageToken', morePagesAvailable);
            console.log(url.toString());
            console.log(morePagesAvailable);
            try {
                  const response = await fetch(
                        url.toString(),
                        initVal)
                  const data = await response.json();
                  console.log(data);
                  addData(data);
            } catch (error) {
                  console.error(error);
            }
            ctr++;
      } while (ctr < 4)
}

// data => object
function addData(object) {
      data.push(object);
      morePagesAvailable = data[0].nextPageToken.toString();
      console.log(morePagesAvailable);   // working: but always the same string     
      console.log(data[0].files[1].id);  // working: but always the same string
}

Why can I connect to a Websocket via STOMP client but can hit it manually with Postman?

I have the following

import { Client } from '@stomp/stompjs';
...
initialize(userId) {
        try {
            addDebugMessage('Initializing WebSocket service');
            addDebugMessage(`User ID: ${userId}`);

            this.userId = userId;
            this.client = new Client({
                brokerURL: 'wss://.....net/gs-guide-websocket', // Try without wss://
                debug: (str) => {
                    addDebugMessage(str, 'debug');
                }
            });

            // Connection handling
            this.client.beforeConnect = () => {
                addDebugMessage('Attempting to connect...');
            };

            this.client.onConnect = (frame) => {
                ....
            };

            this.client.onWebSocketError = (error) => {
                addDebugMessage('WebSocket Error:', 'error');
                addDebugMessage(error, 'error');
                wsStatus.set('error');
            };

            this.client.onStompError = (frame) => {
                addDebugMessage('STOMP Error:', 'error');
                addDebugMessage(`Message: ${frame.headers['message']}`, 'error');
                addDebugMessage(`Body: ${frame.body}`, 'error');
                wsStatus.set('error');
            };

            this.client.onDisconnect = () => {
                addDebugMessage('Disconnected from WebSocket');
                wsStatus.set('disconnected');
            };

            // Attempt connection
            addDebugMessage('Activating STOMP client');
            this.client.activate();

        } catch (error) {
            addDebugMessage(`Initialization error: ${error.message}`, 'error');
            wsStatus.set('error');
        }
}

When I try to connect I get

client.js:285 WebSocket connection to ‘wss://…..net/gs-guide-websocket’ failed:

[WebSocket debug]: Opening Web Socket...
client.js:285 WebSocket connection to 'wss://....net/gs-guide-websocket' failed: 
_createWebSocket @ client.js:285
_connect @ client.js:218Understand this errorAI
WebSocketStore.js:11 [WebSocket error]: WebSocket Error:
WebSocketStore.js:11 [WebSocket error]: Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
WebSocketStore.js:11 [WebSocket debug]: Connection closed to wss://.....net/gs-guide-websocket
WebSocketStore.js:11 [WebSocket debug]: STOMP: scheduling reconnection in 5000ms
WebSocketStore.js:11 [WebSocket info]: Attempting to connect...
WebSocketStore.js:11 [WebSocket debug]: Opening Web Socket...
client.js:285 WebSocket connection to 'wss://....net/gs-guide-websocket' failed: 
_createWebSocket @ client.js:285
_connect @ client.js:218Understand this errorAI
WebSocketStore.js:11 [WebSocket error]: WebSocket Error:
WebSocketStore.js:11 [WebSocket error]: Event {isTrusted: true, type: 'error', target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
WebSocketStore.js:11 [WebSocket debug]: Connection closed to wss://....net/gs-guide-websocket
WebSocketStore.js:11 [WebSocket debug]: STOMP: scheduling reconnection in 5000ms
WebSocketStore.js:11 [WebSocket info]: Attempting to connect...
WebSocketStore.js:11 [WebSocket debug]: Opening Web Socket...

However if I open up a Postman collection and try to hit it I have no problem…

enter image description here

What am I missing why does it work with postman but fail with the browser?

Backend

    override fun configureMessageBroker(config: MessageBrokerRegistry) {
        config.enableSimpleBroker("/topic")
        config.setApplicationDestinationPrefixes("/app")
    }

    override fun registerStompEndpoints(registry: StompEndpointRegistry) {
        registry.addEndpoint("/gs-guide-websocket")
    }

jsGrid with Form Submission

I have a jsGrid that returns the data in the grid. I’m using rowRenderer to also attach a form. So, when you click on one of the rows in the grid then the form is shown. I’m trying to use javascript to submit the form but for some reason the form is not being recognized. It’s being returned as null when I do a console.log.

Can anyone see what I might be doing wrong that my form is not be recognized?

Solution: Attach a javascript function to the Submit button that does a Fetch versus the normal Web for submission. The Fetch will send the information from the form to the server.

Full code

<script>

    var params = "";
    var options = "";
    var term = "";
    var priority = "";
    var tax_exempt = "";
    var voucher_type = "";
    var banner_source = "";
    var banner_source_code = "";
    var date_account_type = "";

    toastr.options = {
      "closeButton": true,
      "debug": false,
      "newestOnTop": false,
      "progressBar": true,
      "positionClass": "toast-top-center",
      "preventDuplicates": false,
      "onclick": null,
      "showDuration": "300",
      "hideDuration": "1000",
      "timeOut": "5000",
      "extendedTimeOut": "1000",
      "showEasing": "swing",
      "hideEasing": "linear",
      "showMethod": "fadeIn",
      "hideMethod": "fadeOut"
    }

    $.datepicker.setDefaults($.datepicker.formatDate( "mm/dd/yy", new Date()));

    var MyDateField = function(config) { jsGrid.Field.call(this, config); };

    MyDateField.prototype = new jsGrid.Field({
      sorter: function(date1, date2) { return new Date(date1) - new Date(date2); },

      insertTemplate: function(value) {
        return this._insertPicker = $("<input>").datepicker({defaultDate: new Date().toLocaleDateString()});
      },

      editTemplate: function(value) {
        return this._editPicker = $("<input>").datepicker().datepicker("setDate", new Date(value).toLocaleDateString());
      },

      insertValue: function(value) { 
        if ($(this._insertPicker).datepicker("getDate") == null)
          {
           return false;
          }
          else
            {
             return this._insertPicker.datepicker("getDate").toLocaleDateString();
            }
      },

      editValue: function(value) {
        if ($(this._editPicker).datepicker("getDate") == null)
          {
           return false;
          }
          else
            {
             return this._editPicker.datepicker("getDate").toLocaleDateString();
            }
      }
    });

    jsGrid.fields.myDateField = MyDateField;


    options = {
      method: "get",
      dataType: "json",
      headers: {
        "Content-Type": "application/json;charset=utf-8",
        "Accept": "application/json;charset=utf-8"
      }
    };

    fetch('......', options)
      .then(response => response.json())
      .then(data => {
         data.forEach(item => {
           term = JSON.parse(item.TERM);
           priority = JSON.parse(item.PRIORITY);
           tax_exempt = JSON.parse(item.TAX_EXEMPT);
           voucher_type = JSON.parse(item.VOUCHER_TYPE);
           banner_source = JSON.parse(item.BANNER_SOURCE);
           banner_source_code = JSON.parse(item.BANNER_SOURCE_CODE);
           date_account_type = JSON.parse(item.DATE_ACCOUNT_TYPE);
           user_id_voucher_types = JSON.parse(item.USER_ID_VOUCHER_TYPES);
           user_id_voucher_type_sources = JSON.parse(item.USER_ID_VOUCHER_TYPE_SOURCES);
           user_id_grants = JSON.parse(item.USER_ID_GRANTS);
           user_id_account_dates = JSON.parse(item.USER_ID_ACCOUNT_DATES);

           jsGridVoucherType();
         });
      })
      .catch((error) => {
         toastr["error"]("Something went wrong.", "Error");
      });


    function jsGridVoucherType() {

      $("#jsGridVoucherType").jsGrid({
          width: "100%",
          height: "auto",

          heading: true,
          editing: false,
          filtering: true,
          inserting: false,
          sorting: true,
          paging: true,
          autoload: true,

          filterRowRenderer: true,
          insertRowRenderer: true,
          editRowRenderer: true,

          pageSize: 50,
          pageButtonCount: 5,

          noDataContent: "<font color=red>No data was returned.</font>",
          deleteConfirm: "Do you really want to delete this Voucher Type?",

          invalidMessage: "",
          invalidNotify: function(args) { var messages = $.map(args.errors, function(error) { return error.message || null; }); },

          rowRenderer: function(item) {
            var row = $("<tr>");
            var subDetail = $('<td colspan="8">').hide();

            var DetailForm = '<html>' +
                             '<body>' +
                             '<div style="padding: 20px 20px 20px 20px; ">' +
                             '<form id="loginForm" class="row g-3 needs-validation" novalidate>' +
                             '<div class="col-md-4">' +
                             '  <label for="validationCustom01" class="form-label">First name</label>' +
                             '  <input type="text" class="form-control" id="validationCustom01" value="Mark" required>' +
                             '  <div class="valid-feedback">Looks good!</div>' +
                             '</div>' +
                             '<div class="col-md-4">' +
                             '  <label for="validationCustom02" class="form-label">Last name</label>' +
                             '  <input type="text" class="form-control" id="validationCustom02" value="Otto" required>' +
                             '  <div class="valid-feedback">Looks good!</div>' +
                             '</div>' +
                             '<div class="col-md-6">' +
                             '  <label for="validationCustom03" class="form-label">City</label>' +
                             '  <input type="text" class="form-control" id="validationCustom03" required>' +
                             '  <div class="invalid-feedback">Please provide a valid city.</div>' +
                             '</div>' +
                             '<div class="col-md-3">' +
                             '  <label for="validationCustom04" class="form-label">State</label>' +
                             '  <select class="form-select" id="validationCustom04" required>' +
                             '    <option selected disabled value="">Choose...</option>' +
                             '    <option>...</option>' +
                             '  </select>' +
                             '  <div class="invalid-feedback">Please select a valid state.</div>' +
                             '  </div>' +
                             '<div class="col-md-3">' +
                             '  <label for="validationCustom05" class="form-label">Zip</label>' +
                             '  <input type="text" class="form-control" id="validationCustom05" required>' +
                             '  <div class="invalid-feedback">Please provide a valid zip.</div>' +
                             '</div>' +
                             '<div class="col-12">' +
                             '  <div class="form-check">' +
                             '    <input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>' +
                             '    <label class="form-check-label" for="invalidCheck">Agree to terms and conditions</label>' +
                             '    <div class="invalid-feedback">You must agree before submitting.</div>' +
                             '  </div>' +
                             '</div>' +
                             '<div class="col-12">' +
                             '  <button class="btn btn-primary" type="submit">Submit</button>' +
                             '</div>' +
                             '</form>' +
                             '</div>' +
                             '</body>' +
                             '</html>';

            items = Object.keys(item);

            for(let key in item){
              if(item.hasOwnProperty(key)){
                switch(key) {
                  case "ROW_NUMBER":
                  case "PIDM":
                  case "ANUMBER":
                  case "AID_YEAR":
                  case "CREATE_DATE":
                    var cell = $("<td align=center>").addClass("jsgrid-cell").append(item[key]);
                    break;

                  default:
                    var cell = $("<td>").addClass("jsgrid-cell").append(item[key]);
                }

                row.append(cell);
              }
            }

            row.click(function() {
              subDetail.toggle();
            })

            subDetail.append(DetailForm );
            return row.add(subDetail);
          },

          controller: {
            loadData: function (filter) {
                        return fetch("....?" +
                                     "pidm=" + filter.PIDM +
                                     "&anumber=" + filter.ANUMBER +
                                     "&student_name=" + filter.STUDENT_NAME +
                                     "&counselor_id=" + filter.COUNSELOR_ID +
                                     "&status=" + filter.STATUS +
                                     "&create_date=" + filter.CREATE_DATE)
                                 .then(response => response.json()) 
                                 .catch((error) => {
                                    toastr["error"]("Something went wrong.", "Error");
                                 });
            },
          },

          fields: [
            { name: "ROW_NUMBER", type: "text", title: "Row Number", align: "left", editing: false, filtering: false, inserting: false },
            { name: "PIDM", type: "text", title: "Student PIDM", align: "left", editing: false, filtering: false, inserting: false },
            { name: "ANUMBER", type: "text", title: "Student ID", align: "center", editing: false, filtering: false, inserting: false },
            { name: "AID_YEAR", type: "text", title: "Aid Year", align: "center", editing: false, filtering: false, inserting: false },
            { name: "STUDENT_NAME", type: "text", title: "Student Name", align: "left", editing: false, filtering: false, inserting: false },
            { name: "COUNSELOR_ID", type: "text", title: "Counselor ID", align: "left", editing: false, filtering: false, inserting: false },
            { name: "STATUS", type: "text", title: "Status", align: "left", editing: false, filtering: false, inserting: false },
            { name: "CREATE_DATE", type: "text", title: "Create Date", align: "left", editing: false, filtering: false, inserting: false }
          ]
      });
    }


let loginForm = document.getElementById("#loginForm");
console.log(loginForm);


</script> 

This is where I’m creating the grid and also attaching the from when a row is click on the grid.


rowRenderer: function(item) {
            var row = $("<tr>");
            var subDetail = $('<td colspan="8">').hide();

            var DetailForm = '<html>' +
                             '<body>' +
                             '<div style="padding: 20px 20px 20px 20px; ">' +
                             '<form id="loginForm" class="row g-3 needs-validation" novalidate>' +
                             '<div class="col-md-4">' +
                             '  <label for="validationCustom01" class="form-label">First name</label>' +
                             '  <input type="text" class="form-control" id="validationCustom01" value="Mark" required>' +
                             '  <div class="valid-feedback">Looks good!</div>' +
                             '</div>' +
                             '<div class="col-md-4">' +
                             '  <label for="validationCustom02" class="form-label">Last name</label>' +
                             '  <input type="text" class="form-control" id="validationCustom02" value="Otto" required>' +
                             '  <div class="valid-feedback">Looks good!</div>' +
                             '</div>' +
                             '<div class="col-md-6">' +
                             '  <label for="validationCustom03" class="form-label">City</label>' +
                             '  <input type="text" class="form-control" id="validationCustom03" required>' +
                             '  <div class="invalid-feedback">Please provide a valid city.</div>' +
                             '</div>' +
                             '<div class="col-md-3">' +
                             '  <label for="validationCustom04" class="form-label">State</label>' +
                             '  <select class="form-select" id="validationCustom04" required>' +
                             '    <option selected disabled value="">Choose...</option>' +
                             '    <option>...</option>' +
                             '  </select>' +
                             '  <div class="invalid-feedback">Please select a valid state.</div>' +
                             '  </div>' +
                             '<div class="col-md-3">' +
                             '  <label for="validationCustom05" class="form-label">Zip</label>' +
                             '  <input type="text" class="form-control" id="validationCustom05" required>' +
                             '  <div class="invalid-feedback">Please provide a valid zip.</div>' +
                             '</div>' +
                             '<div class="col-12">' +
                             '  <div class="form-check">' +
                             '    <input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>' +
                             '    <label class="form-check-label" for="invalidCheck">Agree to terms and conditions</label>' +
                             '    <div class="invalid-feedback">You must agree before submitting.</div>' +
                             '  </div>' +
                             '</div>' +
                             '<div class="col-12">' +
                             '  <button class="btn btn-primary" type="submit">Submit</button>' +
                             '</div>' +
                             '</form>' +
                             '</div>' +
                             '</body>' +
                             '</html>';

            items = Object.keys(item);

            for(let key in item){
              if(item.hasOwnProperty(key)){
                switch(key) {
                  case "ROW_NUMBER":
                  case "PIDM":
                  case "ANUMBER":
                  case "AID_YEAR":
                  case "CREATE_DATE":
                    var cell = $("<td align=center>").addClass("jsgrid-cell").append(item[key]);
                    break;

                  default:
                    var cell = $("<td>").addClass("jsgrid-cell").append(item[key]);
                }

                row.append(cell);
              }
            }

            row.click(function() {
              subDetail.toggle();
            })

            subDetail.append(DetailForm );
            return row.add(subDetail);
          },

The following statement returns null.


let loginForm = document.getElementById("#loginForm");
console.log(loginForm);

Modifying User-Agent in Electron blocks Requests to a specific Domain

I am building a custom Electron-based browser and modifying the User-Agent dynamically for certain domains. However, after removing Electron/* from the User-Agent for a specific demo gaming website, the site fails to load and throws JavaScript errors.

I intercept all outgoing requests and modify the User-Agent in my Electron main.js like this:

session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
    const originalUserAgent = details.requestHeaders['User-Agent'];
    const newUserAgent = getUserAgentForURL(originalUserAgent, details.url);

    console.log('========================');
    console.log('Intercepted Request:');
    console.log('URL:', details.url);
    console.log('Original User-Agent:', originalUserAgent);
    console.log('Modified User-Agent:', newUserAgent);
    console.log('========================');

    details.requestHeaders['User-Agent'] = newUserAgent;
    callback({ cancel: false, requestHeaders: details.requestHeaders });
});

And my user-agent.js modifies the User-Agent like this:

const { app } = require('electron');

const REMOVE_ELECTRON_COMPONENTS = [
  / Electron/([^s]+)/g,  // Removes Electron
  ` ${app.name}/${app.getVersion()}`, // Removes app-specific info
];

function getUserAgentForURL(userAgent, url) {
  if (typeof userAgent !== 'string') {
    console.error(`Error: Expected userAgent to be a string, but got ${typeof userAgent}`);
    return userAgent || 'Mozilla/5.0';
  }

  let componentsToRemove = [...REMOVE_ELECTRON_COMPONENTS];

  // Remove Electron-specific components but keep Chrome
  componentsToRemove.forEach((x) => {
    if (userAgent) {
      userAgent = userAgent.replace(x, '');
    }
  });

  return userAgent;
}

module.exports = { getUserAgentForURL };

Debugging Output:
When I try to access a demo game website, I get the following logs:

========================
Intercepted Request:
URL: https://[removed-domain]/game-assets/other_resources.json
Original User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) my-electron-app/1.0.0 Chrome/132.0.6834.159 Electron/34.0.2 Safari/537.36
Modified User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6834.159 Safari/537.36
========================

However, the website does not load and throws JavaScript errors in the console:

[96308:0201/114327.613:INFO:CONSOLE(5657)] "Uncaught TypeError: Cannot read properties of undefined (reading 'split')", 
source: https://[removed-domain]/build.js (5657)

[96308:0201/114327.616:INFO:CONSOLE(18588)] "Uncaught TypeError: Cannot read properties of null (reading 'length')", 
source: https://[removed-domain]/logo_info.js (18588)

When I do not modify the User-Agent, the website works perfectly and sends the following successful request:

========================
Intercepted Request:
URL: https://[removed-domain]/gs2c/ge/v4/game
Method: POST
Headers: {
  "host": "[removed-domain]",
  "connection": "keep-alive",
  "content-length": "145",
  "accept": "*/*",
  "accept-encoding": "gzip, deflate, br, zstd",
  "accept-language": "en-US",
  "content-type": "application/x-www-form-urlencoded",
  "origin": "https://[removed-domain]",
  "referer": "https://[removed-domain]/gs2c/html5Game.do?extGame=1&symbol..",
  "sec-fetch-dest": "empty",
  "sec-fetch-mode": "cors",
  "sec-fetch-site": "same-origin",
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) my-electron-app/1.0.0 Chrome/132.0.6834.159 Electron/34.0.2 Safari/537.36",
  "sec-ch-ua": ""Not A(Brand";v="8", "Chromium";v="132"",
  "sec-ch-ua-mobile": "?0",
  "sec-ch-ua-platform": ""Windows""
}
========================

How can I successfully modify the User-Agent?

ngx-mask custom directive on primeng components

I need some help to uderstand why i’m struggling to do this :

I got a primeNG datepicker that has an input inside.
I would like to apply the ngx-mask directive to that input, but i can’t find a way that works…

ngx-mask: (https://npmjs.com/package/ngx-mask)

  • I tried applying the mask attributes directly on the datepicker, but it seems it works only on an input.
  • I tried with ViewChild and then setAttribute “mask” on the inner input.
  • I tried with a custom wrapper directive that wraps NgxMaskDirective and provideNgxMask but i’m on angular 18 and it seems the attribute mask from ngx-mask is an InputSignal so it can’t be modified.

Can someone tell me how you think we can solve that ?
I tried with a javascript inputmask lib (https://npmjs.com/package/inputmask) and it works when i apply the directive directly on the datepicker primeng so i think it’s clearly possible !

Just want to try if i can do the same with ngx-mask

Here is the wrapper directive i tried :

import { AfterViewInit, Directive, ElementRef, Inject, Input, InputSignal, Optional } from '@angular/core';
import { NgxMaskDirective, provideNgxMask } from 'ngx-mask';
import { DatePicker } from 'primeng/datepicker';

@Directive({
    selector: 'dateMask',
    providers: [provideNgxMask(), NgxMaskDirective]
})

export class DatePickerMaskDirective implements AfterViewInit {

private ngxMaskDirective: NgxMaskDirective;

constructor(
    private datePicker: ElementRef,
) {}

ngAfterViewInit() {
    const input = this.datePicker.nativeElement.querySelector('input');
    if (input) {
        this.ngxMaskDirective = new NgxMaskDirective();

        this.ngxMaskDirective.writeValue(input.value);

        input.addEventListener('input', (e: Event) => {
            this.ngxMaskDirective.onInput(e as any);
        });
        input.addEventListener('blur', (e: Event) => {
            this.ngxMaskDirective.onBlur(e as any);
        });
    }
}
}


<p-datepicker
    // somes others attributes
    dateMask
    mask="99:99"
    apm="true"
>

Thanks in advance,

How to omit exports of interfaces generated by json2ts (json-schema-to-typescript)?

The way things work in VSCode is that you can create a something.d.ts file and as long as that file does neither import nor export anything, it is considered globally defined within the project.

This is very convenient for augmenting plain JavaScript with advanced type definitions for things such as API responses.

If a .d.ts file does use export however, you are required to import any symbols you want to use. For things like API responses, there is no need to do that as the definitions do not do anything in plain JS. For example, I’d have a file my_response.d.ts:

interface MyResponse {
    name: string;
    someNumber: number;
}

Then in plain JS I can do this:

/** @type {MyResponse} **/
const parsed = JSON.parse(messageString);

And IDE would then hint the fields of MyResponse on that variable.

I generated a .d.ts file using json2ts like this:

json2ts --input ../myschemas/messages.schema.json --output generated_defs/messages_schema.d.ts

But the output has exports for the symbols.

export interface MessagesSchema {
  messages: Message[];
  [k: string]: unknown;
}
export interface Message {
  name: string;
  id: number;
  data: MessageField[];
  [k: string]: unknown;
}

I would like to tell the generator to omit those in this case, so I can use the symbols across the entire project without having to import them. How to do that?

Arranging elements in a skewed circle shape using CSS or JS [closed]

I’m trying to place elements within a skewed circle shape/container, with the main element being placed at the bottom center of the circle, and every other being scaled down the further behind it is.

Please see this image for reference – the numbers represent the elements’ scale.

enter image description here

I want to be able to dynamically insert new elements in the container so they would automatically follow the skewed shape.

I’m currently using the :nth-child() property and manually setting all values – thus meaning reworking all of them when I want to insert something new.

I’m looking for a creative CSS-only or JS solution for this. Any help would be appreciated!

NextJS 15: Error occurred pre-rendering page, with redux toolkit installed

I have created an nextjs 15 app and I have redux toolkit used in it. When I run the build, it throws an error

Error occurred prerendering page "/_not-found". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Failed to fetch data
    at i.execute (/Users/vishnucr/Projects/mise811-sales/.next/server/app/_not-found/page.js:1:3366)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async /Users/vishnucr/Projects/mise811-sales/.next/server/app/_not-found/page.js:1:3955
Export encountered an error on /_not-found/page: /_not-found, exiting the build.
 ⨯ Static worker exited with code: 1 and signal: null

I found the StoreProvider created for Redux Store is the issue, may be I did it wrong. Below is my app structure. It uses AppRouter.

Layout.tsx

import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import Launch from "./launch";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <Launch>{children}</Launch>
      </body>
    </html>
  );
}

Launch.tsx

import React from "react";
import StoreProvider from "@/lib/store/providers/storeProvider";

interface LaunchProps {
  children: React.ReactNode;
}

const Launch = ({ children }: LaunchProps) => {
  /* fetch sales and populate */
  return <StoreProvider>{children}</StoreProvider>;
  // return children;
};

export default Launch;

StoreProvider.tsx

"use client";
import { useRef } from "react";
import { Provider } from "react-redux";
import { makeStore, AppStore } from "@/lib/store/store";

export default function StoreProvider({
  children,
}: {
  children: React.ReactNode;
}) {
  const storeRef = useRef<AppStore>(undefined);
  if (!storeRef.current) {
    // Create the store instance the first time this renders
    storeRef.current = makeStore();
  }

  return <Provider store={storeRef.current}>{children}</Provider>;
}

If I Removed the store provider and returns the {children}, build will be created.

What am I doing wrong here, is This how the store is suppose to be used in NextJS ?