uncaught TypeError: can’t access property “elements”, m is undefined in three.core.js while using three-loader-3dtiles library

I’m experiencing a runtime error when using the three-loader-3dtiles library.

“Uncaught TypeError: can’t access property ‘elements”, m is undefined”. The error occurs when I try to update the runtime using the

  useFrame(({ size, camera }, dt) => {
    if (runtime) runtime.update(dt, size.height, camera);
  });

But If I comment out above line, the error goes away, but the 3D tiles are not rendered.

here is my code
loader-3dtiles-rf3.tsx

import { Loader3DTiles, LoaderProps, Runtime } from 'three-loader-3dtiles';
import { useLoader, useThree, useFrame } from '@react-three/fiber';
import { Loader, Vector2 } from 'three';

class Loader3DTilesBridge extends Loader {
  props: LoaderProps;

  load(url, onLoad, onProgress, onError) {
    const loadTileset = async () => {
      try {
        const result = await Loader3DTiles.load({
          url,
          ...this.props,
          onProgress,
        });
        onLoad(result);
        console.log('result', result);
      } catch (e) {
        console.log('Error loading 3d tiles!', e);
        onError(e);
      }
    };
    loadTileset();
  }
  setProps(props) {
    this.props = props;
  }
}

function Loader3DTilesR3FAsset(props) {
  const threeState = useThree();
  const loaderProps = {
    renderer: threeState.gl,
    viewport: getViewport(threeState.gl),
    options: {
      ...props,
    },
  };

  // TODO: Getting type error
  // @ts-ignore
  const { model, runtime } = useLoader(Loader3DTilesBridge, props.url, (loader: Loader3DTilesBridge) => {
    loader.setProps(loaderProps);
  });

  useFrame(({ size, camera }, dt) => {
    if (runtime) runtime.update(dt, size.height, camera);
  });

  return (
    <group {...props} dispose={runtime.dispose}>
      <primitive object={model} />
    </group>
  );
}
function getViewport(renderer) {
  const viewSize = renderer.getSize(new Vector2());
  return {
    width: viewSize.x,
    height: viewSize.y,
    devicePixelRatio: renderer.getPixelRatio(),
  };
}

export { Loader3DTilesR3FAsset };
import { Loader3DTiles, LoaderProps, Runtime } from 'three-loader-3dtiles';
import { useLoader, useThree, useFrame } from '@react-three/fiber';
import { Loader, Vector2 } from 'three';


class Loader3DTilesBridge extends Loader {
  props: LoaderProps;


  load(url, onLoad, onProgress, onError) {
    const loadTileset = async () => {
      try {
        const result = await Loader3DTiles.load({
          url,
          ...this.props,
          onProgress,
        });
        onLoad(result);
        console.log('result', result);
      } catch (e) {
        console.log('Error loading 3d tiles!', e);
        onError(e);
      }
    };
    loadTileset();
  }
  setProps(props) {
    this.props = props;
  }
}


function Loader3DTilesR3FAsset(props) {
  const threeState = useThree();
  const loaderProps = {
    renderer: threeState.gl,
    viewport: getViewport(threeState.gl),
    options: {
      ...props,
    },
  };


  // TODO: Getting type error
  // @ts-ignore
  const { model, runtime } = useLoader(Loader3DTilesBridge, props.url, (loader: Loader3DTilesBridge) => {
    loader.setProps(loaderProps);
  });


  useFrame(({ size, camera }, dt) => {
    if (runtime) runtime.update(dt, size.height, camera);
  });


  return (
    <group {...props} dispose={runtime.dispose}>
      <primitive object={model} />
    </group>
  );
}
function getViewport(renderer) {
  const viewSize = renderer.getSize(new Vector2());
  return {
    width: viewSize.x,
    height: viewSize.y,
    devicePixelRatio: renderer.getPixelRatio(),
  };
}


export { Loader3DTilesR3FAsset };

and I’m rendering in canva bu rf3 this way

<Canvas shadows style={{ background: '#272730' }}>
        <PerspectiveCamera ref={camera}>
          <Suspense fallback={null}>
            <Loader3DTilesR3FAsset
              dracoDecoderPath={'https://unpkg.com/[email protected]/examples/jsm/libs/draco'}
              basisTranscoderPath={'https://unpkg.com/[email protected]/examples/jsm/libs/basis'}
              rotation={new THREE.Euler(-Math.PI / 2, 0, 0)}
              url="https://int.nyt.com/data/3dscenes/ONA360/TILESET/0731_FREEMAN_ALLEY_10M_A_36x8K__10K-PN_50P_DB/tileset_tileset.json"
              maximumScreenSpaceError={48}
            />
          </Suspense>
        </PerspectiveCamera>
        <OrbitControls camera={camera.current} />
     </Canvas>

Duplicate OrderID detected error in MongoDB

I am getting this error in my console and I use unique for the OrderID, I have tried using UUID, counter and MongoDB code, after I create a first receipt any other one that follows return this message in the console and display internal
Server error

“ Receipt created successfully: ORD00001
About to save receipt with ID: ORD00002
Duplicate orderId ORD00002 detected, retrying…
About to save receipt with ID: ORD00003
Duplicate orderId ORD00003 detected, retrying…
About to save receipt with ID: ORD00004
Duplicate orderId ORD00004 detected, retrying…
About to save receipt with ID: ORD00005
Duplicate orderId ORD00005 detected, retrying…
About to save receipt with ID: ORD00006
Duplicate orderId ORD00006 detected, retrying…””

Why is my tsparticles canvas not showing anything?

I see the canvas tag and element inside the DOM, but I don’t see anything. I’ve searched online everywhere but nothing seems to fix it. I have a mouse glow effect so I tried turning that off since the canvas for that might’ve interfered but it’s still not working.

I am using react and tsparticles

This is my jsx:

import styles from './Hero.module.css';
import { useEffect, useRef } from 'react';
import Typed from 'typed.js';
import Particles from '@tsparticles/react';
import { loadSlim } from '@tsparticles/slim';

export default function Hero() {
    const typedRef = useRef(null);
    const typedInstance = useRef(null);

    const particlesInit = async(main) => {
        await loadSlim(main);
    };

    const particlesLoaded = (container) => {
        console.log(container);

    }

    useEffect(() => {
        typedInstance.current = new Typed(typedRef.current, {
        strings: ['software engineer.', ' student.'],
        typeSpeed: 90,
        backSpeed: 30,
        backDelay: 1000,
        loop: true,
        cursorChar: '|'
    });

    return () => {
      typedInstance.current.destroy();
    };
  }, []);
    return (
        <div className={styles.heroContainer}>
            <Particles
                id="tsparticles"
                init={particlesInit}
                loaded={particlesLoaded}
                options={{
                    background: {
                        color: {
                            value: "transparent",
                        },
                    },
                    fpsLimit: 120,
                    interactivity: {
                        events: {
                            onClick: {
                                enable: false,
                                mode: "push",
                            },
                            onHover: {
                                enable: false,
                                mode: "repulse",
                            },
                            resize: true,
                        },
                        modes: {
                            push: {
                                quantity: 4,
                            },
                            repulse: {
                                distance: 200,
                                duration: 0.4,
                            },
                        },
                    },
                    particles: {
                        color: {
                            value: "#ffffff",
                        },
                        links: {
                            color: "#ffffff",
                            distance: 150,
                            enable: true,
                            opacity: 0.5,
                            width: 1,
                        },
                        collisions: {
                            enable: false,
                        },
                        move: {
                            direction: "none",
                            enable: true,
                            outModes: {
                                default: "bounce",
                            },
                            random: true,
                            speed: 0.5,
                            straight: false,
                        },
                        number: {
                            density: {
                                enable: true,
                                area: 800,
                            },
                            value: 80,
                        },
                        opacity: {
                            value: 0.5,
                        },
                        shape: {
                            type: "circle",
                        },
                        size: {
                            value: { min: 1, max: 3 },
                            random: true,
                        },
                    },
                    detectRetina: true,
                }}
            />
            <div className={styles.main}>
                <p className={styles.greeting}>Hi, I am</p>
                <h1 className={styles.nameContainer}><span className={styles.name}>bob</span></h1>
                <h2 className={styles.secondaryText}>I am a <span ref={typedRef}></span></h2>
            </div>
        </div>
    );
}

and this is my CSS

.heroContainer {
    position:relative;
    overflow:hidden;

    display:flex;
    flex-direction:column;
    justify-content: center;

    max-width:100%;
    height:100vh;
    background-color:#171b22;
}

#tsparticles {
    position:absolute;
    top:0;
    left:0;

    width:100%;
    height:100%;
    z-index:-1;
}

.main {
    position: relative;
    z-index: 2;

    display:flex;
    flex-direction:column;
    justify-content:center;
    width:100%;
    max-width:clamp(600px, 1200px, 1500px);
    
    margin-left:auto;
    margin-right: auto;
    padding-left: 16px;
    padding-right: 16px;

    text-align:left;
    color:#e0e0e0;

}

.greeting, .nameContainer, .secondaryText{
    padding: 0px;
    margin: 0px;
    transition: transform 0.3s ease-in-out;
}

.greeting:hover, .nameContainer:hover, .secondaryText:hover {
    transform: scale(1.05);
}

h1 {
    font-size: 80px;
}

.secondaryText {
    font-size: 25px;
    color:#e0e0e0;
}


p {
    font-size:20px;
    color:#e0e0e0;
}

.name {
    background:linear-gradient(90deg, #ffde0e 10%, #e4a053 60%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;

    text-shadow: 0 0 3px rgba(255, 222, 14, 0.4), 0 0 5px rgba(228, 160, 83, 0.4);
}

h1, h2, p {
    margin: 0px;
}

Zapier Code by Zapier not counting quantities for bundled products in Shopify subscription orders

Problem Summary
I’m using Zapier to extract data from Shopify orders and send it to Google Sheets. Products within subscription bundles are showing quantity 0, when I run tests it counts fine. But, when I get live orders, all the product counts besides the bundle are marked 0.

Setup

  1. **Platform: Shopify + AWTOMIC for bundled subscription meal plans
  2. Site: https://cravemealprepco.com
  3. Google Sheet: Template link of live order, followed by test
  4. Zap Structure:

    a) 1 – Shopify – New Paid Order

    b) 2 – Filter by Zapier → Only continues if line items bundle name includes “Regular”

    c) 3 – Code by Zapier → Process meal data (code below)

    d) 4 – Google Sheets → Create Spreadsheet Row
/*
UPDATED VERSION - Handles both bundle items and individual items
*/

//////////////////// 1. master list - Updated with actual Shopify names ////////////////////
const meals = {
  // Add the actual product names from Shopify
  "Peanut Butter Power Balls": 0,
  "Regular Protein - Meal Plan": 0,
  "Overnight Oats": 0,
  "Protein Donuts ( 2 pack )": 0,
  
  // Keep your existing names in case they're used elsewhere
  "Chocolate Strawberry Protein Pancakes": 0,
  "Crave Breakfast Sandwich (Gluten Free)": 0,
  "BBQ Chicken Mac N' Cheese": 0,
  "French Onion Chicken - (Gluten Free)": 0,
  "Chipotle Chicken (Gluten Free)": 0,
  "Crave Fil A (Gluten Free)": 0,
  "Turkey Bolognese": 0,
  "Fiesta Turkey Bowl (Gluten Free)": 0,
  "Sweet Chili Turkey Bowl (Gluten Free)": 0,
  "Adobo Braised Beef Bowl - (Gluten Free)": 0,
  "Beef Empanada": 0,
  "Sesame Ginger Beef": 0,
  "Big Mac Bowl (Gluten free)": 0,
  "Asian Crunch Salad": 0,
  "Strawberry Walnut Chicken Salad (GF)": 0,
  "Mediterranean Chicken Hummus Wrap": 0,
  "Grilled Chicken Chimichurri Bowl (GF) (DF) (SF)": 0,
  "Grilled Chicken Caesar Wrap": 0,
  "Beef & Broccoli (GF) (DF) (SF)": 0,
  "Steak & Eggs (GF) (DF) (SF)": 0,
  "Pulled Chicken (GF) (DF) (SF)": 0,
  "Turkey Burger (GF) (DF) (SF)": 0,
  "Grilled Chicken (GF) (DF) (SF)": 0,
  "Chili Lime Turkey (GF) (DF) (SF)": 0
};

//////////////////// 2. normalise inputs ////////////////////
const names = Array.isArray(inputData.meal_name)
  ? inputData.meal_name
  : (inputData.meal_name || "").split(/s*,s*/).filter(Boolean);

const qtys = Array.isArray(inputData.meal_qty)
  ? inputData.meal_qty
  : (inputData.meal_qty || "").split(/s*,s*/).filter(Boolean);

//////////////////// 3. Handle bundle data from inputData object ////////////////////
// Check if there are bundle items directly in inputData
const bundleItems = [];
for (const key in inputData) {
  // Look for meal names that end with "- Regular" or "- Double"
  if (key.match(/s*-s*(regular|double)$/i) && typeof inputData[key] === 'string' && !isNaN(inputData[key])) {
    const qty = parseInt(inputData[key], 10);
    if (qty > 0) {
      bundleItems.push({
        name: key,
        qty: qty
      });
    }
  }
}

//////////////////// 4. build the counts ////////////////////
const unknown = [];

// Process regular meal_name/meal_qty arrays
for (let i = 0; i < names.length; i++) {
  let title = (names[i] || "").trim();

  // strip "- Regular" or "- Double" (any case, any spaces)
  title = title.replace(/s*-s*(regular|double)$/i, "").trim();

  const qty = parseInt(qtys[i] || "0", 10);

  if (meals.hasOwnProperty(title)) {
    meals[title] += qty;
  } else {
    unknown.push(title);
  }
}

// Process bundle items found in inputData
for (const item of bundleItems) {
  let title = item.name.trim();
  
  // strip "- Regular" or "- Double" (any case, any spaces)
  title = title.replace(/s*-s*(regular|double)$/i, "").trim();

  if (meals.hasOwnProperty(title)) {
    meals[title] += item.qty;
  } else {
    unknown.push(title);
  }
}

//////////////////// 5. return the row ////////////////////
return {
  name: inputData.billing_name || "",
  phone: inputData.billing_phone || "",
  email: inputData.email || "",
  unknown_titles: unknown,
  ...meals
};

Input Data Structure
The Code by Zapeir step receies:

  1. billing_name: Billing Address Name
  2. billing_phone: Customer Phone
  3. email: Email
  4. meal_qty: Line Items Quantity
  5. meal_name: Line Items Title

Expected Vs Actual Behavior

Expected: When a new order is placed the product quantities should be updated correctly in to the spreadsheet row.

Actual: When a new order is placed the product quantities all show as ‘0’ besides the bundle item. When I run same order as a test it works fine.

Question
How can I make it so that I receive same results (Track the quantity for each meal for new orders and add them to the sheet correctly). I was thinking the issue might be with the JavaScript code.

MutationObserver не работает, когда я нахожусь на другой вкладке Chrome [closed]

Наблюдатель работает, когда я нахожусь на вкладке Chrome, где используется MutationObserver. Я получаю сообщения, когда происходят изменения, но когда я нахожусь на другой вкладке или в другом окне, ничего не происходит, пока я не вернусь на вкладку, где использую MutationObserver.

Например, предположим, что я использую stackoverflow.com на вкладке, где наблюдаю за мутациями. Всё в порядке, я вижу изменения. Затем я оставляю вкладку открытой и переключаюсь на другую вкладку. Мутации перестают работать, как будто DOM не обновляется, пока я не вернусь на предыдущую вкладку.
На сайте идёт обратный отсчёт таймера. Я слежу за этим таймером. Через минуту обновляю страницу. Но когда вкладка неактивна, скрипт перестаёт следить!

вот часть кода:

window.alert = function ( text ) { console.log( 'tried to alert: ' + text ); return true; };
const $span = document.getElementById("countdown");
const options = { subtree: true, childList: true };
const observer = new MutationObserver((mutationsList, observer) => {
for (let mutation of mutationsList){
if (mutation.type === 'childList') {
    if ($span.textContent.split(":")[2]=="00") {
        document.querySelector("#dashboard-sidebar > nav > ul > li.nav-item.active > a").click();
        console.log('%c '+$span.textContent, 'color:red');
    }
}
}
});

if($span)observer.observe($span, options);
console.log(new Date().toLocaleTimeString());

setInterval, который следит за тем же таймером, работает исправно, но через некоторое время засыпает

                setInterval(() => {
                    console.log('%c '+$span.textContent, 'color:red');
                }, 60 * 1000); // 5 minutes (5 * 60 seconds * 1000 ms)

How to interact with a Livewire webpage from an external browser extension?

I’m (very newly) getting into browser extension development so would appreciate any input here on whether or not what I’m trying to do is even possible.

I’m trying to write a browser extension for an external website (not owned by me). The site uses Livewire for a very simple display – think a list of options that can either be selected or unselected. The goal of the extension is to grab a list of the items that are unselected – the respective HTML elements have a particular “badge” (HTML class called “selected” and “unselected”) as part of their child elements when I look at the DOM manually.

I first tried to get the list of selected elements by manually filtering through the DOM with JS but have been running into a lot of issues. When viewing the elements on the page they seem to be divs with wire:id classification, which I can look at child elements of, but sometimes this changes to a wire:snapshot which I can’t get further into.

I’m wondering if there is a good way to do this, tried looking to see if there’s a way to import Livewire library into a JS script and use it to interact with the page, but haven’t been able to find any documentation.

Any advice/suggestions/explanations if I’m misunderstanding how the whole things works would be much appreciated 🙂

Repeat for-loop until condition is false

const [start, setStart] = React.useState(false)
let myArray = [1,2,3,4]

I already have a button that calls setStart to change start between true and false. How to repeatedly iterate through myArray to output its content, such as 1, 2, 3, 4, 1, 2, 3, 4... and stops whenever start is flagged false (upon a button click)? Vice versa when start is true.

For example: (click button, loop starts) 1, 2, 3, 4, 1, 2, 3, (click button, loop terminates)

My attempt at implementing a while-loop:

while(start){

  for(let i of myArray){

    if(!start) break;
    setTimeout(console.log(i), 500)
    
  }
}

however it runs into an infinite loop.

Really appreciate any help!

How to send model and some other parameters from javascript to controller using jquery.ajax?

I have an ASP.NET Core MVC project and I am trying to send a model and some other parameter from JavaScript to a controller action in the manner.

const urlAction = window.location.origin + "/UserAccount/ConfirmContact";
const jqXHR = $.ajax({
    method: "POST",
    url: urlAction,
    data: { model: model, contactType: contactType },
    contentType: "application/json; charset=utf-8"
});
await jqXHR?.then(
    async function(data, textStatus, jqxhr)
    {
        alert(`request to ${urlAction} is successed`);
    },
    function(jqxhr, textStatus, errorThrown)
    {
        alert(`request to ${urlAction} is failed; status: ${textStatus}; error: ${errorThrown}`);
    });

My model:

public enum ContactType : int
{
    EMail = 0,
    PhoneNumber
}
public class AccountViewModel : ModelBase
{
    public string? UserId { get; set; }
    public string? UserName { get; set; }
    public string Password { get; set; }
    public string PasswordConfirmation { get; set; }
    public bool TwoFactorEnabled { get; set; }
    public TwoFactorMethod TwoFactorMethod { get; set; }
    public string? Email { get; set; }
    public string? PhoneNumber { get; set; }
    public ContactConfirmationState EmailConfirmationState { get; set; }
    public ContactConfirmationState PhoneConfirmationState { get; set; }
    public string Name { get; set; }
    public string? EsiaLogin { get; set; }
    public string? EsiaPassword { get; set; }
    public string EsiaPasswordConfirmation { get; set; }
    public AccountViewModel()
    {
    }
}

On the controller side:

[HttpPost]
public async Task<IActionResult> ConfirmContact(AccountViewModel model, ContactType contactType)
{
    if(model != null)
    {
        if(contactType == ContactType.PhoneNumber)
        {
            if(await PhoneConfirmationService.SendVerificationCode(model))
            {
                model.PhoneConfirmationState = ContactConfirmationState.AwaitingConfirmation;
            }
        }
        else
        {
            if(await EmailConfirmationService.SendVerificationCode(HttpContext, model))
            {
                model.EmailConfirmationState = ContactConfirmationState.AwaitingConfirmation;
            }
        }
    }
    return View("Register", model ?? new AccountViewModel());
}

But the action parameters are not initialized from the request, but with a default value.
How to send the data correctly?

How to get an empty NodeList?

Is there a way to get an empty NodeList? We could get away with something like

document.querySelectorAll('#a>#b>#c')

and even put it in a wrapper function that iterates as long as it gets an empty NodeList to make it safe. But I’m wondering if there is an “elegant” way of getting an instanceof NodeList which happens to have length of 0. Fiddled around with new NodeList() but without any success.

How to get groupedColumnDefs in sidebar and flat columnDefs in the grid?

AGgrid cdocumentaion here shows custom colum layout but on a click of a button https://www.ag-grid.com/react-data-grid/tool-panel-columns/#custom-column-layout. How can I get different columLayouts in sideBar and Grid. I have exploring with chatGPT and copilot but no luck. This is the code am trying

function AgIndex() {
  //const [isEditing, setIsEditing] = useState(true);
  const gridRef = useRef(null);
  const columnDefs = [
    { field: "salary", colId: "salary" },
    { field: "bonus", colId: "bonus" },
    { field: "name", colId: "name" },
    { field: "department", colId: "department" },
  ];

  const groupedColumnLayout = [
    {
      headerName: "Salary Info",
      groupId: "salary_info",
      children: [{ colId: "salary" }, { colId: "bonus" }],
    },
    {
      headerName: "Personal Info",
      groupId: "personal_info",
      children: [{ colId: "name" }, { colId: "department" }],
    },
  ];

  const rowData = [
    { salary: 50000, bonus: 5000, name: "Alice", department: "Engineering" },
    { salary: 60000, bonus: 7000, name: "Bob", department: "Marketing" },
    { salary: 55000, bonus: 6000, name: "Charlie", department: "HR" },
  ];
  const apiRef = useRef(null);
  const sideBar = {
    toolPanels: [
      {
        id: "columns",
        labelDefault: "Columns",
        iconKey: "columns",
        toolPanel: "agColumnsToolPanel",
        toolPanelParams: {
          suppressSyncLayoutWithGrid: true,
          columnLayout: groupedColumnLayout,
          suppressRowGroups: true,
          suppressValues: true,
          suppressPivots: true,
          suppressPivotMode: true,
          suppressColumnMove: true,
        },
      },
    ],
    defaultToolPanel: "columns",
  };

  const setCustomGroupLayout = useCallback(() => {
    const columnToolPanel = gridRef.current.api.getToolPanelInstance("columns");
    if (columnToolPanel) {
      columnToolPanel.setColumnLayout(groupedColumnLayout);
    }
  }, [groupedColumnLayout]);

  // useEffect(() => {
  //   setCustomGroupLayout();
  // }, []);

  const onGridReady = useCallback((params) => {
    apiRef.current = params.api;
    params.api.openToolPanel("columns");
    requestAnimationFrame(() => {
      setCustomGroupLayout();
    });

  }, []);


  return (
    <div>
      <div className="ag-theme-alpine" style={{ height: 500, width: "100%" }}>
        <AgGridReact
          ref={gridRef}
          rowData={rowData}
          columnDefs={columnDefs}
          defaultColDef={{ resizable: true, sortable: true, filter: true }}
          sideBar={sideBar}
          onGridReady={onGridReady}
          //onFirstDataRendered={onFirstDataRendered}
        />
      </div>
    </div>
  );
}````

UnknownDependenciesException [Error]: Nest can’t resolve dependencies of the MysqlAgendaRepository (?)

Im getting “[ExceptionHandler] UnknownDependenciesException [Error]: Nest can’t resolve dependencies of the MysqlAgendaRepository (?). Please make sure that the argument “AgendaRepository” at index [0] is available in the AgendaModule context.” everytime i start my application. I use MysqlAgendaRepository as concrete implementation and AgendaRepository as a abstration implementation.

agenda.module.ts:

import { Module } from '@nestjs/common';
import { AgendaService } from './agenda.service';
import { AgendaController } from './agenda.controller';
import { Agenda } from './entities/agenda.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MysqlAgendaRepository } from './repositories/agenda.mysql.repository';

@Module({
  imports:[TypeOrmModule.forFeature([Agenda])],
  providers: [AgendaService, { provide: "AgendaRepository", useClass: MysqlAgendaRepository}
  ],
  controllers: [AgendaController]
})
export class AgendaModule {}

How to Create a Nested Array from 2 Tables in Angular

I have 2 tables that I need to display in the following manner:
Nested Table
I’m populating 2 different arrays

storeTableData: any=[];
employeeTableData: any=[];

The storeTableData has the following fields: StoreID, Name, Address
The employeeTableData has the following fields: StoredID, Name, Role

I’m not sure if I have to turn my data into an array like this first (and if so, how?):

Store[] = [
{
  StoreID: "1",
  Store: "Staples",
  address: "123 Main Street, San Diego CA 12345",
  employees: [
    {
      StoreID: "1",
      Name: "John Doe",
      Role: "Manager"
    },
    {
      StoreID: "1",
      Name: "John Smith",
      Role: "Cashier"
    },
    {
      StoreID: "1",
      Name: "Jane Doe",
      Role: "Shipping"
    },
},
{
  StoreID: "2",
  Store: "Best Buy",
  address: "456 Main Street, San Diego CA 12345",
  employees: [
    {
      StoreID: "2",
      Name: "John Smith",
      Role: "Manager"
    },
    {
      StoreID: "2",
      Name: "Jane Doe",
      Role: "Cashier"
    },
    {
      StoreID: "2",
      Name: "John Doe",
      Role: "Shipping"
    },
},
]

Or is there a way I can just do it via a nested ngif in the html or is there some other way?

Firebase SignInWithRedirect with Apple login fails on a nuxtjs / js app

I believe a Nuxt.js (Vue.js) web app with Firebase is correctly set up, as I’m able to log in with Firebase/Apple using signInWithPopup.

I have properly set my custom domain in the Auth domain settings. The problem only occurs when signing in with redirect.

Here is my implementation:
I click on the “Sign in with Apple” button, which triggers the corresponding function. I am correctly redirected to Apple’s sign-in page. I enter my credentials and am redirected back to the sign-in page. Absolutely nothing happens—no error message, nothing.

The result from getRedirectResult is always null.

I tried moving the getRedirectResult block into onMounted, but it changed nothing.

So, how can I get getRedirectResult to correctly pick up the sign-in process?


<script setup lang="ts">
// Define page meta to use appropriate layout
definePageMeta({
  layout: 'web-no-tab-bar'
});

useSeoMeta({
  title: 'Sign-In'
});

import { httpsCallable } from 'firebase/functions'
import { GoogleAuthProvider, OAuthProvider, signInWithPopup, updateProfile, getAdditionalUserInfo, signInWithRedirect, getRedirectResult, getAuth } from 'firebase/auth'
import { doc, getDoc, Firestore } from 'firebase/firestore'


// Store instances
const authStore = useAuthStore()
const flashStore = useFlashStore()


// Firebase instances
const { $auth, $firestoreDb, $functionsInstance } = useNuxtApp()
const auth = getAuth();

getRedirectResult(auth)
  .then((result) => { //-----------> ALWAYS NULL
   
    // Check if result is not null before processing
    if (result) {
      alert('result')
      const credential = OAuthProvider.credentialFromResult(result);
      if (credential) {
        // You can also get the Apple OAuth Access and ID Tokens.
        const accessToken = credential.accessToken;
        const idToken = credential.idToken;
      }
      // The signed-in user info.
      const user = result.user;
    }
  })
  .catch((error) => {
    // Handle Errors here.
    const errorCode = error.code;
    const errorMessage = error.message;
    // The email of the user's account used.
    const email = error.customData.email;
    // The credential that was used.
    const credential = OAuthProvider.credentialFromError(error);

    // ...
  });





/**
* ================================
*  Apple Sign-In
* ================================
*/
const signInWithApple = async () => {
  try {
    const provider = new OAuthProvider('apple.com')
    // Configure Apple provider with required scopes
    provider.addScope('email')
    provider.addScope('name')

    const result = await signInWithRedirect($auth, provider)

  } catch (err: any) {
    // eslint-disable-next-line no-console
    console.error('Apple sign-in failed:', err)
    flashStore.show(err?.message || 'Apple sign-in failed. Please try again.')
  }
}


/**
* ================================
*  Providers Sign-In
* ================================
*/

// Verify user profile after authentication. Not for email sign-in. For providers.
const checkUserProfileAfterProvidersSignIn = async (userId: string) => {
  try {
    const userDoc = await getDoc(doc($firestoreDb as Firestore, 'users', userId))

    // If missing username or country, treat as new user
    if (!userDoc.exists() || !userDoc.data()?.username || !userDoc.data()?.country) {
      navigateTo('/authentication/user-info-collect')
    } else {
      // Persist user country in localStorage for later use
      if (utils.isLocalStorageAvailable()) {
        const key = `selectedCountry_${userId}`
        window.localStorage.setItem(key, userDoc.data()?.country.toLowerCase())
      }

      // Redirect back to the page the visitor came from (or home)
      const target = utils.isLocalStorageAvailable()
        ? window.localStorage.getItem('previousUrlForAfterSignIn') || '/'
        : '/'
      navigateTo(target)
    }
  } catch (err) {
    // eslint-disable-next-line no-console
    console.error('Error verifying user profile after Google sign-in:', err)
    navigateTo('/')
  }
}


// Store previous URL in localStorage for future redirect handling
onMounted(() => {
  if (utils.isLocalStorageAvailable()) {
    const previousUrl = (window.history.state && window.history.state.back) || document.referrer || '/';
    localStorage.setItem('previousUrlForAfterSignIn', previousUrl);
  }

});
</script>

Create a Regex for a ‘+’ delimited file for JS

I have a file delimited by + signs. I want to convert those to comma delimited so I can create a csv.
At first I was using simply this regex:
/+/ but then I found out that the file contains data like this:
km aaa+aaa so I created created this regex for such cases /(?<![Kk]m[^+]*)+/g. This last one worked pretty well, but it didn’t work in cases like this:

AA +BBB  +km 12,    +ccccccc
AA +BBB  +km 530,   +ccccccc

Since it returns something like this:

"AA ","BBB  ","km 12,    +ccccccc"
"AA ","BBB  ","km 530,    +ccccccc"

Instead of:

"AA ","BBB  ","km 12,    ","ccccccc"
"AA ","BBB  ","km 530,   ","ccccccc"

Any idea what regex pattern could help?