AdminJS not overriding default dashboard with custom React component

So, I just started with adminjs and have been trying to override the default dashboard with my own custom component. I read the documentation and I don’t think I am doing anything wrong? yet it still wont load the component. I started with a basic component to see whether it works or not.
It’s being initialized but its not overriding the default dashboard.

AdminJS initialized with dashboard: { component: 'Dashboard' }

Code is provided below
Dashboard.jsx:

import React from 'react';
import { Box } from '@adminjs/design-system';
import { useTranslation } from 'adminjs';

const Dashboard = () => {
    const { translateMessage } = useTranslation();
    console.log('dashboard component loading...')
    return (
        <Box>
            <h1>{translateMessage('helloMessage', 'Hello')}</h1>
        </Box>
    );
};

export default Dashboard;

admin.js:

import AdminJS from 'adminjs';
import { Database, Resource } from '@adminjs/sequelize';
import Customers from './src/models/Customers.js';
import Product from './src/models/Product.js';
import People from './src/models/People.js';
import Companies from './src/models/Companies.js';
import Leads from './src/models/Leads.js';
import Offers from './src/models/Offers.js';
import { ComponentLoader } from 'adminjs';

const componentLoader = new ComponentLoader();

const Components = {
    Dashboard: componentLoader.add('Dashboard', './src/components/Dashboard.jsx')
};

AdminJS.registerAdapter({ Database, Resource });

const adminOptions = {
    dashboard: {
        component: Components.Dashboard
    },
    componentLoader,
    resources: [{
        resource: Customers,
        options: {
            parent: null,
            properties: {
                id: {
                    isVisible: { list: false, edit: false, show: false },
                },
                type: {
                    position: 1,
                    availableValues: [
                        { value: 'company', label: 'Company' },
                        { value: 'person', label: 'Person' },
                    ],
                },
                name: {
                    position: 2,
                },
                email: {
                    position: 3,
                },
                phone: {
                    position: 4,
                },
                country: {
                    position: 5,
                },
            },
        },
    },
    {
        resource: People,
        options: {
            parent: null,
        },
    },
    {
        resource: Companies,
        options: {
            parent: null,
        },
    },
    {
        resource: Leads,
        options: {
            parent: null,
            properties: {
                type: {
                    availableValues: [
                        { value: 'company', label: 'Company' },
                        { value: 'person', label: 'Person' },
                    ],
                },
            },
        },
    },
    {
        resource: Offers,
        options: {
            parent: null,
        },
    },
    {
        resource: Product,
        options: {
            parent: null,
        },
    },
    ],
    rootPath: '/admin',
};

export default adminOptions;

server.js:

import AdminJS from 'adminjs'
import AdminJSExpress from '@adminjs/express'
import express from 'express'
import dotenv from 'dotenv'
import sequelize from './src/config/db.js';
import { Database, Resource } from '@adminjs/sequelize';
import adminOptions from './admin.js';

dotenv.config();

const PORT = 3000;

const start = async () => {
    const app = express()
    AdminJS.registerAdapter({ Database, Resource });
    const admin = new AdminJS(adminOptions);
    console.log('AdminJS initialized with dashboard:', admin.options.dashboard);


    const adminRouter = AdminJSExpress.buildRouter(admin)
    app.use(admin.options.rootPath, adminRouter)

    app.listen(PORT, async () => {
        console.log(`AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`)

        try {
            await sequelize.authenticate();
            console.log("database connected successfully")

            await sequelize.sync();
            console.log("database models synchronized")
        }
        catch (err) {
            console.log("error connecting to database", err)
        }
    })
}

start()

I tried logging any information regarding it but it seems like it’s not loading the component at all?
Any help or suggestions would be appreciated. Thanks!

Next.js with Drizzle ORM: Page not refreshing after task creation/update

I’m working on a Next.js project with Drizzle ORM where I can create and update tasks. After submitting the task form, I get navigated back to the homepage, but the new/updated task isn’t displayed until I manually refresh the page. Here’s the relevant code:

TaskForm.tsx (Client Component):

const onSubmit = async (values) => {
  const response = 
    type === OperationType.Create 
      ? await addTask(values) 
      : await updateTask(defaultValues?.id ?? 0, { ...defaultValues, ...values });

  toast(response.message);

  if (response.success) {
    form.reset();
    router.refresh(); // Trying to refresh the page
    router.push(redirect ?? "/"); // Redirect to homepage after submission
  }
};

app/page.tsx (Server Component):

export const revalidate = 0; // Disable ISR

export default async function Home() {
  const tasks = await getTasks();
  const completedTasks = tasks.filter(task => task.isCompleted);
  const incompleteTasks = tasks.filter(task => !task.isCompleted);

  return (
    <div className="container">
      <h1>Incomplete Tasks</h1>
      <TodoListTable data={incompleteTasks} />
      <h1>Completed Tasks</h1>
      <CompletedListTable data={completedTasks} />
    </div>
  );
}

actions.ts (Server Actions for Drizzle ORM):

export async function addTask(task) {
  try {
    db.insert(tasks).values(task).run();
    return { success: true, message: "Task created successfully" };
  } catch (error) {
    return { success: false, message: "Error creating task" };
  }
}

The task is created or updated successfully, but when the page navigates back to the homepage, I don’t see the new task unless I manually refresh the page.

What I’ve Tried:

  • I’ve used router.refresh() to refetch the page, but it doesn’t seem to update the homepage’s data after task submission.
  • I disabled ISR using export const revalidate = 0; in app/page.tsx to make sure that fresh data is fetched every time.
  • Tried both router.replace() and router.push() but no difference in behavior.

What am I missing? How can I ensure the homepage always reflects the updated task list after submission without a manual refresh?

Using appwrite, with error: ‘Cannot use import statement outside a module’

I have been trying to get google sign in to work on my site but no matter what I do it still wont work. This time it says ‘Uncaught SyntaxError: Cannot use import statement outside a module ‘ and I KNOW what it wants me to fix but I dont know HOW to fix it here is my code:

inGame.js

import { account} from './appwrite'

const loginBtn = document.getElementById('login-btn')
const logoutBtn = document.getElementById('logout-btn')
const srofileScreen = document.getElementById('profile-screen')
const loginScreen = document.getElementById('login-screen')

async function handleLogin (){
  account.createOAuth2Session(
    'google', //app
    'https://volive-io.github.io/DungeonDwellers/',    //succses
    'https://volive-io.github.io/DungeonDwellers/fail',    //fail
  )
}


async function getUser (){
  try {

    const user = await account.get()
    renderProfileScreen(user)
  }catch(error) {
    renderLoginScreen()
  }
}

function renderLogingScreen (){
  profileScreen.classList.remove('hidden')
}

function renderProfileScreen (user){
  document.getElementById('user-name').textContent = user.name
  profileScreen.classList.remove('hidden')
}

async function handleLogout (){
  accont.deleteSession('current')
  profileScreen.classList.add('hidden')
  renderLoginScreen()
}
  

Now my ‘appwrite.js’:

import { Client, Account } from 'appwrite';

export const client = new Client();

client
    .setEndpoint('https://cloud.appwrite.io/v1')
    .setProject('66ec18fc0015b7a013d5'); 

export const account = new Account(client);
export { ID } from 'appwrite';

Now my html:

<head>
    <title>DungeonDwellers</title>
    <script src="ingameScript.js"></script>
    <script src="appwrite.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
    <link rel="shortcut icon" href="icon.png" type="image/x-icon"/>
</head>
<body>
    <div id="welcome">
        <h1>Welcome to DungeonDwellers!</h1>
    </div>
    <div id="options">
        <button id="Start_Game" onclick="StartGame()">Start Game</button>
        <div id="login-screen" class="hidden">
            <button id="login-btn">Login with Google</button>
        </div>
        <div class="hidden" id="profile-screen">
            <p>Welcome <span id="user-name"></span>!</p>
            <button id="logout-btn">Logout</button>
        </div>
    </div>
</body>

Im sorry that was a lot of code and text, but I am burnt out of ideas and time. I have worked on this for at least 4 hours and have had not much progress. I am open to any suggestions!

I originally tried the old google dev docs method from 8 years ago, but it don’t work so I found a youtube tutorial and this is what I got. It worked from them but it is not working for me; here is the vid Setup Google OAuth sign in 6 minutes

P.S. I will me gone for a while after this post, but will get get to your answers soon. Thanks for reading and trying to help.

What is the Regex for mm/dd/yy format that includes single digit months and days?

I am trying to figure out the proper regex to assert dates in the following format: mm/dd/yy. The date can display single and double digits for the months and days. There is no zero in front of the single digit. So January 1st, 2024 would look like this: 1/1/2024.

Below is what I use for an assertion in Cypress, but when there is a single digit in the month, date or both, it fails. Can anyone tell me what might be the issue?

var dateFormatRegex= /(0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)dd/;

Recording audio in Unity WebGL game

I am trying to provide recording functionality (save gameplay as video file) for my Unity WebGL game.
I can easily record video stream (via javascript plugin) as

let canvasStream = canvas.captureStream();

But I fail to record audio.
I can go with

stream = await navigator.mediaDevices.getUserMedia(constraints);

But I don’t like this method. It creates popup, interrupting the game. I’d like it to go smoothly, without interruption.

I see the WEBAudio object created on the page with WEBAudio.audioInstances, WEBAudio.audioContext, etc. But I failed to get audio stream from there.
No errors logged and no audio in my recording. Just video.

Appreciate your help and advice on how to get Audio Stream from any of these available objects:

WEBAudio
WEBAudio.audioContext
WEBAudio.audioContext.destination
WEBAudio.audioInstances[1].buffer
WEBAudio.audioInstances[1].getNumberOfChannels()
WEBAudio.audioInstances[2].gain

Thank you.

Load title tilts one after the other and asset animations on load

I’m trying to recreate this title load and fade – that is features on the az-black site

https://az-black.webflow.io/

Reduced speed by 20%

enter image description here

0– the page sits a little further down at the edge of the sticky (jumps to that spot on load – if near top)

1– MEET tilts first

2– BLACK tilts second

3– text reduces size and phone image fades in and slides to top


current code in this section thats handling the intro load poorly – also should this being uses refs instead of getIds — from what I can tell it scroll snaps to a point where the title text is sticky and the phone naturally moves further up clearing the text.

https://codesandbox.io/p/sandbox/focused-goldwasser-forked-dk957k

  //make effects in mobile image & texts ...
  React.useEffect(() => {
    document
      .getElementById("makeEffectInto-left-Text")
      ?.classList.add("makeEffectIntoText");
    document
      .getElementById("makeEffectInto-right-Text")
      ?.classList.add("makeEffectIntoText-2");

    setTimeout(() => {
      let textfontSize = document.getElementById("meedtextone");
      let textfontSize2 = document.getElementById("meedtextone2");
      textfontSize.style.fontSize = "14vw";
      textfontSize2.style.fontSize = "14vw";
      document
        .getElementById("imageId-forRemove-hiddhen")
        ?.classList.remove("hidden");
      document
        .getElementById("imageId-forRemove-hiddhen2")
        ?.classList.remove("hidden");
      document
        .getElementById("hiddenImageComesFromDown")
        ?.classList.add("imageId-forRemove-hiddhenmain");
    }, 1200);
  }, []);

the parallax effect that follows may work well with this solution – but I am unsure if they will conflict

const iphone = document.querySelector('.iphone-holder'),
  backgroundText = document.querySelector('.hero-text-holder')

document.addEventListener('mousemove', e => {
  const halfWindow = window.innerWidth/2,
    xVal = e.pageX - halfWindow,
    positionInWindow = (xVal/window.innerWidth),
    pct = 10 * positionInWindow
  
  iphone.style.transform = `translateX(${pct}%)`
  backgroundText.style.transform = `translateX(${-0.3*pct}%)`

})

Web Bluetooth characteristicvaluechanged not triggered in Android Chrome but works in Desktop Chrome

I’m working on a web application that connects to a heart rate monitor using the Web Bluetooth API. The code works perfectly in Desktop Chrome, where the characteristicvaluechanged event is triggered as expected after connecting to the device. However, when I try this on Android Chrome, everything seems to go well — the device connects and starts notifications, but the characteristicvaluechanged event is never fired.

Here’s the code:

async connectHeartRateMonitor() {
    if (this.device) return this.connect();
    if (!(navigator as any).bluetooth?.requestDevice) {
        return alert("Your device does not support Web Bluetooth API.");
    }

    try {
        this.device = await (navigator as any).bluetooth.requestDevice({
            filters: [{ services: ['heart_rate'] }],
            optionalServices: ['battery_service', 'device_information']
        });

        this.device.addEventListener('gattserverdisconnected', this.onDisconnected.bind(this));
        this.connect();
    } catch (error) {
        console.error('Error:', error);
    }
}

private connect() {
    this.device.gatt.connect().then(async () => {
        const service = await this.device.gatt.getPrimaryService('heart_rate');
        this.characteristic = await service.getCharacteristic('heart_rate_measurement');
        await this.characteristic.startNotifications();
        this.characteristic.addEventListener('characteristicvaluechanged', this.handleHeartRateData.bind(this));
        console.log('Connected and notifications started.');
    }).catch(error => {
        console.error('Error connecting:', error);
    });
}

private handleHeartRateData(event) {
    const heartRate = event.target.value.getUint8(1);
    console.log('Heart Rate:', heartRate);
}

In both Desktop Chrome and Android Chrome, I can connect to the heart rate monitor. However, on Android, the characteristicvaluechanged event never triggers after notifications are started.

Any ideas why this event isn’t firing on Android Chrome? Is there something different about how Web Bluetooth works on mobile that I need to account for?

Edit:

Here is the live demo on Plunker. Unfortunately, Bluetooth connections don’t work inside an iframe, so I’m also sharing the direct URLs for testing:

https://plnkr.co/edit/phLtTl0l8JWBWwm2?preview
https://run.plnkr.co/preview/cm1a1vs4500063j75dwrozsfm/

If the direct preview URLs expire, you can go to the Plunker editor and click “open the preview in separate window” where the page will load directly and allow connecting to Bluetooth devices.

eval JavaScript function works only when copied, pasted and run first in Developer console using chrome Developer tools

: i have a function

function myfunc() {
    var SS1 = 16;
    AA = [0,1,2,3,4];
    AA[i] = 1,
    AA[x] = 2,
    console.log(AA[i])
}

if i do

eval(myfunc.toString().replace('SS1', 'SS2')); 

nothing happens , unless i copy the function, paste it in console and run it 1st, then value will change.

any idea how to fix that.

for now i have a snippet :

eval(myfunc.toString().replace('SS1', 'SS2')); 
myfunc ;

this prints the function in console, i click on it, copy it from source where it displays when clicked on, paste it in console, then run the snippet again, it changes values.

How to select the last record for each record type in a MongoDB with typescript and mongoose

I’ve got a mongoDB collection that looks like:

[
 {user: "joe",  event: "foo", timestamp: 1},
 {user: "meg",  event: "blah", timestamp: 2},
 {user: "rick", event: "bork", timestamp: 3},
 {user: "joe",  event: "bing", timestamp: 4},
 {user: "meg",  event: "biz",  timestamp: 5},
 {user: "tim",  event: "boz",  timestamp: 6}
]

and I want to find the latest event for each user, so get a set of results like:

[
 {user: "rick", event: "bork", timestamp: 3},
 {user: "joe",  event: "bing", timestamp: 4},
 {user: "meg",  event: "biz",  timestamp: 5},
 {user: "tim",  event: "boz",  timestamp: 6}
]

I’ve looked over the mongoose aggregation framework docs, and it seems like there should be a way to do this simply, but none of the examples I’ve seen do quite exactly this. Lots of them group by user, but then the resulting groupings lose some of the data, and I’m not sure how to reconstitute the full documents at the end.

React router dom 6.22 multiple level nested children routes index page not rendering

I have multiple nested routes in, however the index route component that is 2 levels deep is not rendering and just showing a blank page.

// I cannot add an `index` property because you can't have child routes if it is an index route.


export const routes= [
  { 
    // Put a navigate element since index routes cannot have children. 
    // If this navigate is removed, it cannot reroute using index.
    element: () => <Navigate to={`one`} />,
    path: '/',
    name: 'default',
    children: [
      {
        // Once it is navigated to here from the default `/` route, it just renders a blank page and not the component `NestedComponentOne`
        element: NestedComponentOne,
        path: 'one',
        name: 'One',
        children: [
          {
            element: DeeplyNestedComponentOne,
            name: 'Deep One',
            path: 'deep-one',
          },
          {
            element: DeeplyNestedComponentTwo,
            name: 'Deep Two',
            path: 'deep-two',
          },
        ]
      },
    ]
  }
]


const MyComponent= () => {
  return (
    <>
      <div style={{ margin: "0px 0px" }}>
        <Routes>
          {routes.map((route, idx) => {
            if (route.children && route.children.length > 0) {
              return (
                <Route
                  key={`child-routes-auth-${idx}`}
                  element={route?.element && <route.element />}
                  errorElement={route?.errorElement}
                  name={route.name}
                  path={route.path}
                >
                  {route.children.map((childRoute, childIdx) => {
                    if (childRoute.children && childRoute.children.length > 0) {
                      return (
                        <Route
                          key={`inner-child-auth-routes-${childIdx}`}
                          element={childRoute?.element && <childRoute.element />}
                          errorElement={childRoute?.errorElement}
                          name={childRoute.name}
                          path={childRoute.path}
                        >
                          {childRoute.children.map((innerRoutes, innerIndex) => {
                            return (
                              innerRoutes.element && (
                                <Route
                                  key={`nested-inner-auth-${innerIndex}`}
                                  element={innerRoutes?.element && <innerRoutes.element />}
                                  errorElement={innerRoutes?.errorElement}
                                  index={innerRoutes?.index}
                                  name={innerRoutes.name}
                                  path={innerRoutes.path}
                                />
                              )
                            )
                          })}
                        </Route>
                      )
                    }
                    return (
                      childRoute.element && (
                        <Route
                          key={`childIdx-auth-${childIdx}`}
                          element={childRoute?.element && <childRoute.element />}
                          errorElement={childRoute?.errorElement}
                          index={childRoute?.index}
                          name={childRoute.name}
                          path={childRoute.path}
                        />
                      )
                    )
                  })}
                </Route>
              )
            }
            return (
              route.element && (
                <Route
                  key={`top-routes-${idx}`}
                  element={<route.element />}
                  errorElement={route?.errorElement}
                  index={route?.index}
                  path={route.path}
                  name={route.name}
                />
              )
            )
          })}
        </Routes>
      </div>
    </>
  );
}

How to have eCharts tooltip fully visible in the page with Bootstrap

I was trying to implement a Bootstrap 5.x design for some eCharts graphs.

But the tooltip goes out of the page and only part of it is visible.

The code it’s too long to put in stackoverflow snippet so I made a Jsfiddle as example.

See this:

https://jsfiddle.net/18g0op7c/

the chart it’s included in a div tag like this:

<div id="A" style="width: 100%; height: 100px; background-color: rgb(102, 102, 102);">
  <div id="mainchart" style="width: 100%; height: 100%;">
    
  </div>
</div>

So the question it’s:

How to have eCharts tooltip fully visible in the page with Bootstrap?

Adding and removing selections from an array for a compensation calculator

codepen: https://codepen.io/strozilla/pen/abVYbrx

const compensationRates = {
    10: { single: 171.23 },
    20: { single: 338.49 },
    30: {
        single: 524.31,
        withSpouse: 586.31,
        withSpousewithoneParent: 636.31,
        withSpousewithTwoParents: 686.31,
        singlewithOneParent: 574.31,
        singlewithTwoParents: 624.331,
        singlewithOneChild: 565.31,
        withSpousewithOneChild: 632.21,
        withSpousewithOneParentwithOneChild: 682.31,
        withSpousewithTwoParentswithOneChild: 732.31,
        singlewithOneParentwithOneChild: 615.31,
        sinlgewithTwoParentswithOneChild: 665.31,
        additionalChildUnder18: 31.0,
        additionalChildOver18: 100.0,
        aidAndAttendance: 57.0
    },
    40: {
        single: 755.28,
        withSpouse: 838.28,
        withSpousewithOneParent: 904.28,
        withSpousewithTwoParents: 970.28,
        withOneParent: 821.28,
        withTwoParents: 887.28,
        withOneChild: 810.28,
        withSpousewithOneChild: 899.28,
        withSpousewithOneParentwithOneChild: 965.28,
        withSpousewithTwoParentswithOneChild: 1031.28,
        withOneParentwithOneChild: 876.28,
        withTwoParentswithOneChild: 942.28,
        additionalChildUnder18: 41.0,
        additionalChildOver18: 133.0,
        aidAndAttendance: 76.0
    },
    50: {
        single: 1075.16,
        withSpouse: 1179.16,
        withSpousewithOneParent: 1262.16,
        withSpousewithTwoParents: 1345.16,
        withOneParent: 1158.16,
        withTwoParents: 1144.16,
        withOneChild: 1241.16,
        withSpousewithOneChild: 1255.16,
        withSpousewithOneParentwithOneChild: 1338.16,
        withSpousewithTwoParentswithOneChild: 1421.16,
        withOneParentwithOneChild: 1227.16,
        withTwoParentswithOneChild: 1310.16,
        additionalChildUnder18: 51.0,
        additionalChildOver18: 167.0,
        aidAndAttendance: 95.0
    },
    60: {
        single: 1361.88,
        withSpouse: 1486.88,
        withSpousewithOneParent: 1586.88,
        withSpousewithTwoParents: 1686.88,
        withOneParent: 1461.88,
        withTwoParents: 1561.88,
        withOneChild: 1444.88,
        withSpousewithOneChild: 1577.88,
        withSpousewithOneParentwithOneChild: 1677.88,
        withSpousewithTwoParentswithOneChild: 1777.88,
        withOneParentwithOneChild: 1544.88,
        withTwoParentswithOneChild: 1644.88,
        additionalChildUnder18: 62.0,
        additionalChildOver18: 200.0,
        aidAndAttendance: 114.0
    },
    70: {
        single: 1716.28,
        withSpouse: 1861.28,
        withSpousewithOneParent: 1978.28,
        withSpousewithTwoParents: 2095.28,
        singlewithOneParent: 1833.28,
        singlewithTwoParents: 1950.28,
        singlewithOneChild: 1813.28,
        withSpousewithOneChild: 1968.28,
        withSpousewithOneParentwithOneChild: 2085.28,
        withSpousewithTwoParentswithOneChild: 2202.28,
        singlewithOneParentwithOneChild: 1930.28,
        singlewithTwoParentswithOneChild: 2047.28,
        additionalChildUnder18: 72.0,
        additionalChildOver18: 234.0,
        aidAndAttendance: 134.0
    },
    80: {
        single: 1995.01,
        withSpouse: 2161.01,
        withSpousewithOneParent: 2294.01,
        withSpousewithTwoParents: 2427.01,
        singlewithOneParent: 2128.01,
        singlewithTwoParents: 2261.01,
        singleithOneChild: 2106.01,
        withSpousewithOneChild: 2283.01,
        withSpousewithOneParentwithOneChild: 2416.01,
        withSpousewithTwoParentswithOneChild: 2549.01,
        singlewithOneParentwithOneChild: 2239.01,
        singlewithTwoParentswithOneChild: 2372.01,
        additionalChildUnder18: 82.0,
        additionalChildOver18: 267.0,
        aidAndAttendance: 153.0
    },
    90: {
        single: 2241.91,
        withSpouse: 2428.91,
        withSpousewithOneParent: 2578.91,
        withSpousewithTwoParents: 2728.91,
        singlewithOneParent: 2391.91,
        singlewithTwoParents: 2541.91,
        singlewithOneChild: 2366.91,
        withSpousewithOneChild: 2565.91,
        withSpousewithOneParentwithOneChild: 2715.91,
        withSpousewithTwoParentswithOneChild: 2865.91,
        singlewithOneParentwithOneChild: 2516.91,
        singlewithTwoParentswithOneChild: 2666.91,
        additionalChildUnder18: 93.0,
        additionalChildOver18: 301.0,
        aidAndAttendance: 172.0
    },
    100: {
        single: 3737.85,
        withSpouse: 3946.25,
        withSpousewithOneParent: 4113.51,
        withSpousewithTwoParents: 4280.77,
        singlewithOneParent: 3905.11,
        singlewithTwoParents: 4072.37,
        singlewithOneChild: 3877.22,
        withSpousewithOneChild: 4098.87,
        withSpousewithoneParentwithOneChild: 4266.13,
        withSpousewithTwoParentswithOneChild: 4433.39,
        singlewithOneParentwithOneChild: 4044.48,
        singlewithTwoParentswithOneChild: 4211.74,
        additionalChildUnder18: 1033.55,
        additionalChildOver18: 334.49,
        aidAndAttendance: 191.14
    }
}

let limb = []
let disabilities = []
let bilateralDisabilities = []
let selectedOptions = []
let selectionsDisplay
let compensation
let totalCompensation = 0
let combinedPercentage = 0
let selectedBodyPart = null
let resultSpan = document.getElementById('result')

function roundToNearest10(value) {
    return Math.round(value / 10) * 10
}

function calculateCompensation() {
    document.querySelectorAll('.body-part').forEach(function (bodyPart) {
        bodyPart.addEventListener('click', function () {
            selectedBodyPart = bodyPart.getAttribute('data-body-limb')
        })
    })

    document.querySelectorAll('.percentage').forEach(function (button) {
        button.addEventListener('click', function () {
            let value = parseInt(button.value)
            let selectionText = ''

            if (selectedBodyPart) {
                selectionText = `${selectedBodyPart} ${value}%`
                limb.push(selectedBodyPart) // Add to the limb array

                // Check if there are already limbs with the same data-body-part
                const matchingLimb = limb.filter((l) => l === selectedBodyPart)
                console.log(matchingLimb + ' matching limbs')

                // If there's more than one of the same body part, it's bilateral
                if (matchingLimb.length > 1) {
                    bilateralDisabilities = bilateralDisabilities.concat(disabilities)
                    disabilities.length = 0
                    bilateralDisabilities.push(value)
                } else {
                    disabilities.push(value)
                }

                selectedBodyPart = null // Reset the selected body part after it's used
            } else {
                if (bilateralDisabilities.length > 1) {
                    selectionText = `${value}%`
                    bilateralDisabilities.push(value)
                } else {
                    selectionText = `${value}%`
                    disabilities.push(value)
                }
            }
            console.log(value)
            console.log(disabilities + ' disabilities')
            console.log(bilateralDisabilities + ' bilateral disabilities')

            console.log(limb + ' limb')

            addSelectionBox(selectionText)

            console.log(bilateralDisabilities + ' bilateral 1')
            button.classList.remove('selected')
            updateTotalCompensation()
        })
    })

    document.querySelectorAll('.optional').forEach(function (element) {
        element.addEventListener('change', function () {
            updateTotalCompensation()
        })
    })
    compensation.innerHTML = '$' + totalCompensation.toFixed(2)
    resultSpan.innerHTML = combinedPercentage + '%'

    updateTotalCompensation()
}

function updateTotalCompensation() {
    compensation = document.getElementById('compensation')

    selectionsDisplay = document.getElementById('selectionsDisplay')
    if (selectionsDisplay.childNodes.length === 0) {
        combinedPercentage = 0
        totalCompensation = 0
        document.getElementById('result').innerHTML = '0%'
        document.getElementById('compensation').innerHTML = '$0.00'
        return
    }

    if (disabilities.length > 0) {
        combinedPercentage =
            disabilities.reduce(function (acc, cur) {
                return acc * (1 - cur / 100)
            }, 1) * 100
        combinedPercentage = 100 - combinedPercentage
        combinedPercentage = roundToNearest10(combinedPercentage)

        totalCompensation = compensationRates[combinedPercentage]['single']
    }

    if (bilateralDisabilities.length > 0) {
        var bilateralCombined =
            bilateralDisabilities.reduce(function (acc, cur) {
                return acc * (1 - cur / 100)
            }, 1) * 100
        bilateralCombined = 100 - bilateralCombined + 10
        bilateralCombined = roundToNearest10(bilateralCombined)

        console.log(bilateralCombined + ' bilateral combined')

        totalCompensation = compensationRates[bilateralCombined]['single']
        combinedPercentage = bilateralCombined
    }

    compensation.innerHTML = '$' + totalCompensation.toFixed(2)
    document.getElementById('result').innerHTML = combinedPercentage + '%'

    console.log(disabilities + ' disabilities')
    console.log(bilateralCombined + ' bilateral combined')
    console.log(combinedPercentage + ' bilateral 3')
    console.log(totalCompensation + ' bilateral 4')

    selectedOptions = []
    if (selectedOptions.length > 0) {
        document.querySelectorAll('.optional:checked').forEach(function (optional) {
            if (optional.id !== 'none') {
                selectedOptions.push(optional.id)
            }
            console.log(selectedOptions + ' first selected options')
        })

        totalCompensation =
            compensationRates[combinedPercentage][selectedOptions.join('')]
        compensation.innerHTML = '$' + totalCompensation.toFixed(2)
        document.getElementById('result').innerHTML = combinedPercentage + '%'
        console.log(combinedPercentage + ' combined percentage after bilateral')
    }
    // Watch dropdowns for changes
    var childrenUnder18 = parseInt(
        document.getElementById('childrenUnder18').value
    )
    var childrenOver18 = parseInt(document.getElementById('childrenOver18').value)

    // Update selectedOptions array
    if (childrenUnder18 > 0) {
        if (!selectedOptions.includes('withOneChild')) {
            selectedOptions.push('withOneChild')
            totalCompensation =
                compensationRates[combinedPercentage][selectedOptions.join('')]
            console.log(selectedOptions + ' inside under 18')
            console.log(totalCompensation + ' with one child')
        }

        if (childrenUnder18 > 1 && childrenOver18 === 0) {
            let addChildUnder18 = childrenUnder18 - 1
            console.log(addChildUnder18)
            if (addChildUnder18 > 0) {
                totalCompensation +=
                    addChildUnder18 *
                    compensationRates[combinedPercentage]['additionalChildUnder18']
                console.log(totalCompensation + ' with addtnl Child')
            }
        } else if (childrenOver18 > 1 && childrenUnder18 > 0) {
            totalCompensation +=
                childrenUnder18 *
                compensationRates[combinedPercentage]['additionalChildUnder18']
            console.log(totalCompensation + ' with addtnl Child')
        } else {
            totalCompensation =
                compensationRates[combinedPercentage][selectedOptions.join('')]
        }
    } else {
        selectedOptions = selectedOptions.filter(
            (option) => option !== 'withOneChild'
        )
    }

    if (childrenOver18 > 0) {
        if (!selectedOptions.includes('withOneChild')) {
            selectedOptions.push('withOneChild')
        }

        if (childrenOver18 > 1 && childrenUnder18 === 0) {
            let addChildOver18 = childrenOver18 - 1
            if (addChildOver18 > 0) {
                totalCompensation +=
                    addChildOver18 *
                    compensationRates[combinedPercentage]['additionalChildOver18']
            }
        } else if (childrenUnder18 > 1 && childrenOver18 > 0) {
            totalCompensation +=
                childrenOver18 *
                compensationRates[combinedPercentage]['additionalChildOver18']
        } else {
            totalCompensation = compensationRates[combinedPercentage]['withOneChild']
        }
    } else {
        selectedOptions = selectedOptions.filter(
            (option) => option !== 'withOneChild'
        )
    }

    console.log(selectedOptions + ' last options')
    console.log(totalCompensation + ' total compensation')
    // Update total compensation display

    compensation.innerHTML = '$' + totalCompensation.toFixed(2)
    document.getElementById('result').innerHTML = combinedPercentage + '%'
}

document
    .getElementById('childrenUnder18')
    .addEventListener('change', updateTotalCompensation)
document
    .getElementById('childrenOver18')
    .addEventListener('change', updateTotalCompensation)

function addSelectionBox(text) {
    selectionsDisplay = document.getElementById('selectionsDisplay')
    let box = document.createElement('div')
    box.className = 'selection-box'
    box.innerHTML = `${text} <span class="remove-box">X</span>`
    selectionsDisplay.appendChild(box)

    box.querySelector('.remove-box').addEventListener('click', function () {
        removeSelection(text, box)
    })
}

function removeSelection(text, box) {
    let value

    if (text.endsWith('%')) {
        value = parseInt(text)

        // Remove from disabilities
        let index = disabilities.indexOf(value)
        if (index !== -1) {
            disabilities.splice(index, 1)
        }

        // Remove from bilateralDisabilities
        index = bilateralDisabilities.indexOf(value)
        if (index !== -1) {
            bilateralDisabilities.splice(index, 1)
        }
    } else {
        // Remove limb selection
        const limbToRemove = text
        const limbIndex = limb.indexOf(limbToRemove)
        if (limbIndex !== -1) {
            limb.splice(limbIndex, 1)
        }
    }

    console.log('Updated disabilities:', disabilities)
    console.log('Updated bilateral disabilities:', bilateralDisabilities)

    box.remove()

    // Determine if we need to switch back from bilateral to disabilities
    if (limb.length > 1) {
        // Check if any limb selections are still present
        const allLimbSelections = limb.filter((l) => l === selectedBodyPart)
        if (allLimbSelections.length <= 1) {
            // Reassign bilateralDisabilities to disabilities if only one or none
            disabilities = disabilities.concat(bilateralDisabilities)
            bilateralDisabilities.length = 0 // Clear bilateralDisabilities array
        }
    }

    // Recalculate combined percentage and total compensation
    updateTotalCompensation()
}

function clearTotals() {
    document
        .querySelectorAll('input[type="checkbox"]')
        .forEach(function (checkbox) {
            checkbox.checked = false
            let label = checkbox.closest('label')
            if (label) {
                label.classList.remove('checked')
            }
        })
    document.getElementById('childrenUnder18').value = '0'
    document.getElementById('childrenOver18').value = '0'
    limb = []
    disabilities = []
    bilateralDisabilities = []
    selectedOptions = []
    totalCompensation = 0
    combinedPercentage = 0

    var selectionsDisplay = document.getElementById('selectionsDisplay')
    selectionsDisplay.innerHTML = ''

    compensation = document.getElementById('compensation')
    compensation.innerHTML = '$' + 0.0
    document.getElementById('result').innerHTML = 0 + '%'

    updateTotalCompensation()
}

document.addEventListener('DOMContentLoaded', (event) => {
    function handleCheckboxChange(event) {
        const group = event.target.closest('div')
        const checkboxes = group.querySelectorAll('.optional')

        checkboxes.forEach((checkbox) => {
            if (checkbox !== event.target) {
                checkbox.checked = false
                const otherLabel = checkbox.closest('label')
                otherLabel.classList.remove('checked')
            }
        })

        let label = event.target.closest('label')
        if (event.target.checked) {
            label.classList.add('checked')
        } else {
            label.classList.remove('checked')
        }

        updateTotalCompensation()
        console.log(totalCompensation)
    }

    document.querySelectorAll('.optional').forEach((checkbox) => {
        checkbox.addEventListener('change', handleCheckboxChange)
    })
})

calculateCompensation()

<div class="calculator">
    <h2>Veteran Disability Calculator</h2>
    <div class="instructions"><span>Enter your disabilities using the buttons below.</span>
    <span>If your disability is on an extremity push that proper leg or arm button then push the percentage</span></div>
    

<div class="body-part-sec">
    <div class="top-left">
        <button class="body-part arm" type="button" data-body-limb="arm">Left Arm</button>
    </div>
    <div class="top-right">
        <button class="body-part arm" type="button" data-body-limb="arm">Right Arm</button>
    </div>
    <div class="bottom-left">
        <button class="body-part leg" type="button" data-body-limb="leg">Left Leg</button>
    </div>
    <div class="bottom-right">
        <button class="body-part leg" type="button" data-body-limb="leg">Right Leg</button>
    </div>
</div>

<div>
 <div class="selections">
            <button class="percentage" value="10">10%</button>
            <button class="percentage" value="20">20%</button>
            <button class="percentage" value="30">30%</button>
            <button class="percentage" value="40">40%</button>
            <button class="percentage" value="50">50%</button>
            <button class="percentage" value="60">60%</button>
            <button class="percentage" value="70">70%</button>
            <button class="percentage" value="80">80%</button>
            <button class="percentage" value="90">90%</button>
            <button class="percentage" value="100">100%</button>
        </div>
</div>
<div id="selectionsDisplay" class="selections-display"></div>

    <div class="options-sec">
        <div class="marital-status">
            <div>What is Your Marital Status?</div>
            <label class="checked"><input class="optional" type="checkbox" id="single">Single</label>
            <label><input class="optional" type="checkbox" id="withSpouse">Married</label>
        </div>
        <div class="dependent-parents">
            <div>Do You Have Any Dependent Parents?</div>
            <label class="checked"><input class="optional" type="checkbox" id="none">None</label>
            <label><input class="optional" type="checkbox" id="withOneParent">One Parent</label>
            <label><input class="optional" type="checkbox" id="withTwoParents">Two Parents</label>
        </div>
    </div>

  <div class="dependent-children-container">
    <div class="dependent-children">
        <label for="childrenUnder18">Dependent Children Under 18: </label>
        <select class="dependent-dropdown" id="childrenUnder18">
            <option id="0" value="0">0</option>
            <option id="1" value="1">1</option>
            <option id="2" value="2">2</option>
            <option id="3" value="3">3</option>
            <option id="4" value="4">4</option>
            <option id="5" value="5">5</option>
            <option id="6" value="6">6</option>
            <option id="7" value="7">7</option>
            <option id="8" value="8">8</option>
            <option id="9" value="9">9</option>
            <option id="10" value="10">10</option>
            </select>
        </div>
        <div class="dependent-children">
            <label for="childrenOver18">Dependent Children Over 18:</label>
            <select class="dependent-dropdown" id="childrenOver18">
                <option id="11" value="0">0</option>
                <option id="12" value="1">1</option>
                <option id="13" value="2">2</option>
                <option id="14" value="3">3</option>
                <option id="15" value="4">4</option>
                <option id="16" value="5">5</option>
                <option id="17" value="6">6</option>
                <option id="18" value="7">7</option>
                <option id="19" value="8">8</option>
                <option id="20" value="9">9</option>
                <option id="21" value="10">10</option>
            </select>
        </div>
    </div>

  <div class="estimated-total">
    <div class="percent-dollar">
        <div class="totals">Combined Disability: <span id="result">0%</span></div>
        <div class="totals">Estimated Monthly Compensation: <span id="compensation">$0.00</span></div>
    </div>
    <button id="clearSelections" class="clear-btn" onclick="clearTotals()">Clear Selections</button>
  </div>
</div>

I have a calculator that is supposed to give an estimated disability compensation. The calculation part is fairly straight forward, there is one calculation for just disabilities, then if you select two arms or two legs, the calculation is different.

When adding selections I seem to be getting the correct calculations, but the issue happens when I try to remove a selection. It should remove the percentage from the array and recalculate. This works if I remove a selection that is just a percentage, but if it is a limb + percentage, it does not recalculate correctly. Looking at the console, the removeSelection function is not removing those percentages from the array, which is weird because they’re only numbers in the array. So not sure why one gets removed but the other doesn’t.
Also, if you have advice on a simpler way to do this, that would be greatly appreciated. Thanks!

I was wondering if this JavaScript piece of code is ok

I’m new to JavaScript and I’m having trouble doing this question and I was wondering if this can work. This is the task.

Write a function toIPv4, which allows the caller to pass 4 String
values and returns a valid IP Address as a String. In your solution,
you must do the following:

  1. Use either arguments or a Rest Parameter to accept multiple values to your function
  2. Make sure the caller passes exactly 4 parameters, error if not
  3. Make sure all 4 values are Strings, error if not
  4. Convert each string value to a number (Integer) and make sure it is in the range 0-255, error if not
  5. If all of the above checks pass, use a Template Literal to return the IP Address as a String
  6. Use the functions from questions 1 and 2 to help you solve 1-5 above For example, toIPv4(“192”, “127”, “50”, “1”) should return
    “192.127.50.1”
function toIPv4(...args) {
  // Check if exactly 4 arguments are passed
  if (args.length !== 4) {
    throw new Error('You must pass exactly 4 parameters.');
  }

  // Check if all arguments are strings and are valid numbers in the range 0-255
  const numbers = args.map(arg => {
    if (typeof arg !== 'string') {
      throw new Error('All arguments must be strings.');
    }
    const num = parseInt(arg, 10); // Convert the string to a number (integer)
    if (isNaN(num) || num < 0 || num > 255) {
      throw new Error('Each string must represent a valid number between 0 and 255.');
    }
    return num;
  });

  // Use Template Literal to return the IP Address as a String
  return `${numbers[0]}.${numbers[1]}.${numbers[2]}.${numbers[3]}`;
}

I’m trying to put the example as the input and it doesn’t work

Issue with CORS when hitting API using LangChain.js with MERN stack [duplicate]


I am using LangChain.js in my MERN stack project and I am importing the following:

import { ChatGoogleGenerativeAI } from "@langchain/google-genai";

Scenario:

  • In my frontend, I am hitting an API endpoint /llm/response which is supposed to interact with Google AI via LangChain.

  • The issue I am facing is that from the frontend I get a CORS error, something like:

    Access to XMLHttpRequest at ‘http://localhost:3000/api/llm/response’ from origin ‘http://localhost:5173’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. `.

  • However, when I test the same API endpoint separately using Postman, it works fine and gives me a response.

Additional observations:

  • When I directly interact with Google AI via LangChain.js from the frontend, it works without any CORS issue, but my API key gets exposed, which is a security risk.

  • I created another endpoint in the backend called /test to check CORS from the frontend through this endpoint, and it gives no error and works fine. So, I don’t think this is a typical CORS error.

Question:

How can I resolve this CORS issue, or what am I missing here?

What I tried and what I was expecting:

  • I tried hitting the /llm/response endpoint from my frontend expecting it to work just like it does in Postman without CORS issues, but instead, I got a CORS error.
  • I also tried setting up a backend proxy to resolve the issue, but it didn’t work. I expected that hitting the API from the frontend would securely interact with the API without exposing my API key.

Get referral code from telegram bot start parameter with JavaScript landing page, and send to Laravel backend

I am making a telegram miniapp, it have options for users to refere others to the app and get reward,
I have completed the authentication and many functions/logics of the app. But extracting the referral code from the ref link eg: https://t.me/my_bot?start=RefC0d3, I have tried a lot of things that did not work

Please can someone help me out, Im stcucked here.
Thanks.

My js code is below:

const telegramWebApp = await loadTelegramSdk();
                if (telegramWebApp) {
                    const { id, first_name, username, start_param } = telegramWebApp.initDataUnsafe;
                    console.log('Telegram User Info:', { id, first_name, username, start_param });
    
                    const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
    
                    const headers = {
                        'Content-Type': 'application/json',
                    };
    
                    if (csrfToken) {
                        headers['X-CSRF-TOKEN'] = csrfToken;
                    }
                    
                    const requestBody = {
                        ...telegramWebApp.initDataUnsafe,
                        referral_code: start_param // Add referral_code to the request body
                    };
    
                    const response = await fetch("{{ route('tg.authenticate') }}", {
                        method: 'POST',
                        headers: headers,
                        body: JSON.stringify(requestBody) // Send referral_code in the request body
                    });
    
                    const data = await response.json();
                    if (data.message === 'Logged in successfully' || data.message === 'User created and logged in') {
                        console.log(`Welcome ${first_name || username}!`);
                        setTimeout(() => {
                            window.location.href = '{{ route('tg.dashboard') }}'; // Redirect after 1.5 seconds
                        }, 1500);
                    } else {
                        console.error('Authentication failed:', data.message);
                    }
                }

In my controller I used Log::info('Request Input:', $request->all()); to check the inputs but the javasacipt is not sending the refferral code.