conditional rendering a table in next js

I have a table of values with varying values of location. I am trying to filter the rows in the database by matching the location value. The code is

'use client';
import { useState, useEffect } from 'react';
import { io } from 'socket.io-client';

const styles = {
  container: {
    width: '100%',
    height: '100vh',
    display: 'flex',
    flexDirection: 'column',
    backgroundColor: '#fff',
    overflow: 'hidden',
  },
  header: {
    width: '100%',
    padding: '1rem',
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    borderBottom: '1px solid #eaeaea',
    boxSizing: 'border-box',
  },
  createButton: {
    padding: '0.5rem 1rem',
    backgroundColor: '#0070f3',
    color: 'white',
    border: 'none',
    borderRadius: '5px',
    cursor: 'pointer',
    fontSize: '1rem',
  },
  headerText: {
    flex: 1,
    textAlign: 'center',
    fontSize: '1.25rem',
    color: '#333',
  },
  logOutButton: {
    padding: '0.4rem 1rem',
    backgroundColor: '#FF999C',
    color: 'white',
    border: '0.5px',
    borderRadius: '5px',
    cursor: 'pointer',
    fontSize: '1rem',
  },
  contentWrapper: {
    flex: 1,
    padding: '1rem',
    overflowY: 'auto',
  },
  main: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    width: '100%',
  },
  table: {
    width: '100%',
    borderCollapse: 'collapse',
    borderRadius: '10px',
    overflow: 'hidden',
    border: '1px solid #000',
    boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
  },
  th: {
    border: '1px solid #000',
    padding: '8px',
    paddingLeft: '10px',
    backgroundColor: '#334',
    color: '#fff',
    textAlign: 'center',
  },
  td: {
    border: '1px solid #000',
    padding: '8px',
    textAlign: 'center',
    backgroundColor: '#FAF9F6',
    color: '#000',
  },
  footer: {
    padding: '0.5rem',
    borderTop: '2px solid #eaeaea',
    display: 'flex',
    justifyContent: 'center',
    backgroundColor: 'white',
    color: 'black',
    boxSizing: 'border-box',
  },
  modalOverlay: {
    position: 'fixed',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%',
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 1000,
  },
  modalContent: {
    backgroundColor: 'white',
    padding: '2rem',
    borderRadius: '10px',
    width: '90%',
    maxWidth: '600px',
    boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)',
  },
  input: {
    width: '100%',
    padding: '0.5rem',
    marginBottom: '0.5rem',
    color: 'black',
    borderRadius: '5px',
    border: '1px solid #ccc',
    fontSize: '1rem',
  },
  modalButtons: {
    display: 'flex',
    justifyContent: 'space-between',
  },
  addButton: {
    padding: '0.5rem 1rem',
    backgroundColor: '#0070f3',
    color: 'white',
    border: 'none',
    borderRadius: '5px',
    cursor: 'pointer',
    fontSize: '1rem',
  },
  cancelButton: {
    padding: '0.5rem 1rem',
    backgroundColor: '#E97451',
    color: 'white',
    border: 'none',
    borderRadius: '5px',
    cursor: 'pointer',
    fontSize: '1rem',
  },
  deleteButton: {
    padding: '0.1rem 1rem',
    backgroundColor: '#E97451',
    color: 'white',
    border: 'none',
    borderRadius: '5px',
    cursor: 'pointer',
    fontSize: '0.8rem',
  },
  '@media (max-width: 1024px)': {
    container: {
      padding: '0.5rem',
    },
    headerText: {
      fontSize: '1rem',
    },
    createButton: {
      padding: '0.3rem 0.6rem',
      fontSize: '0.875rem',
    },
    table: {
      width: '100%',
    },
    modalContent: {
      width: '80%',
    },
  },
  '@media (max-width: 768px)': {
    container: {
      padding: '0.5rem',
    },
    headerText: {
      fontSize: '1rem',
    },
    createButton: {
      padding: '0.3rem 0.6rem',
      fontSize: '0.875rem',
    },
    table: {
      width: '100%',
    },
    modalContent: {
      width: '90%',
    },
  },
  '@media (max-width: 480px)': {
    container: {
      padding: '0.25rem',
    },
    header: {
      flexDirection: 'column',
      alignItems: 'flex-start',
    },
    createButton: {
      padding: '0.3rem 0.5rem',
      fontSize: '0.75rem',
    },
    headerText: {
      fontSize: '0.875rem',
    },
    table: {
      fontSize: '0.875rem',
    },
    modalContent: {
      width: '95%',
    },
  },
};


const Dashboard = () => {
  const [streetLights, setStreetLights] = useState([]);
  const [filter, setFilter] = useState({ location: '' });
  const [selectedLocation, setSelectedLocation] = useState('');
  const [newLight, setNewLight] = useState({
    id: '',
    dateOfFixing: '',
    intensity: '',
    workingCondition: '',
    location: '',
  });
  const [editingLight, setEditingLight] = useState(null);
  const [isModalOpen, setIsModalOpen] = useState(false);

  // Fetch street lights when the filter changes
  useEffect(() => {
    const fetchStreetLights = async () => {
      const query = new URLSearchParams(filter).toString();  // Convert filter to query string
      const res = await fetch(`/api/streetlights?${query}`); // Append query string to the API endpoint
      const data = await res.json();
      setStreetLights(data); // Update state with filtered data
    };
  
    fetchStreetLights();
  }, [filter]); // Re-run the effect when the filter changes
  

  
  useEffect(() => {
    const interval = setInterval(() => {
      const fetchStreetLights = async () => {
        const query = new URLSearchParams(filter).toString();
        const res = await fetch(`/api/streetlights?${query}`);
        const data = await res.json();
        setStreetLights(data);
      };

      fetchStreetLights();
    }, 100);

    return () => clearInterval(interval);
  }, [filter]);

  // Socket connection for real-time updates
  useEffect(() => {
    const socket = io('http://localhost:3001');

    socket.on('streetLightsData', (data) => {
      setStreetLights(data);
    });

    return () => {
      socket.disconnect();
    };
  }, []);

  const handleFilterChange = (e) => {
    setFilter({ ...filter, [e.target.name]: e.target.value });  // Update the filter state
  };
  

  const handleDelete = async (id) => {
    const res = await fetch(`/api/streetlights/${id}`, {
      method: 'DELETE',
    });

    if (res.ok) {
      setStreetLights((prev) => prev.filter((light) => light.id !== id));
    } else {
      console.error('Failed to delete street light');
    }
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setNewLight((prev) => ({
      ...prev,
      [name]: value,
    }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    const res = await fetch('/api/streetlights', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(newLight),
    });

    if (res.ok) {
      const newLight = await res.json();
      setStreetLights((prev) => [...prev, newLight]);
      setNewLight({
        id: '',
        dateOfFixing: '',
        intensity: '',
        workingCondition: true,
        location: '',
      });
    }
  };

  const startEditing = (light) => {
    setEditingLight(light);
    setIsModalOpen(true);
  };

  const handleEditChange = (e) => {
    const { name, value } = e.target;
    setEditingLight((prev) => ({
      ...prev,
      [name]: value,
    }));
  };

  const handleOpenModal = () => {
    setIsModalOpen(true);
  };

  const handleCloseModal = () => {
    setIsModalOpen(false);
  };

  const handleLogout = () => {
    window.location.href = '/api/auth/logout';
  };

  return (
    <div style={styles.container}>
      <header style={styles.header}>
        <button style={styles.createButton} onClick={handleOpenModal}>
          Create Light
        </button>
        <div style={styles.headerText}>Street Lights Dashboard</div>
        <button style={styles.logOutButton} onClick={handleLogout}>
          Log out
        </button>
      </header>
      <header style={styles.header}>
        <div>
          <select
            name="location"
            value={filter.location}
            onChange={handleFilterChange}
            style={styles.input}
          >
            <option value="">All Locations</option>
            <option value="Sriperumbudur">Sriperumbudur</option>
            <option value="Location2">Location 2</option>
            <option value="Location3">Location 3</option>
          </select>
        </div>
        <div style={styles.headerText}>Street Lights Dashboard</div>
      </header>

      <div style={styles.contentWrapper}>
        <main style={styles.main}>
          <table style={styles.table}>
            <thead>
              <tr>
                <th style={styles.th}>ID</th>
                <th style={styles.th}>Date of Fixing</th>
                <th style={styles.th}>Intensity</th>
                <th style={styles.th}>Status</th>
                <th style={styles.th}>Location</th>
                <th style={styles.th}>Actions</th>
              </tr>
            </thead>
            <tbody>
            {streetLights.length > 0 ? (
              streetLights.map((light) => (
                <tr key={light.id}>
                  <td style={styles.td}>{light.id}</td>
                  <td style={styles.td}>{light.dateOfFixing}</td>
                  <td style={styles.td}>{light.intensity}</td>
                  <td style={styles.td}>{light.workingCondition}</td>
                  <td style={styles.td}>{light.location}</td>
                  <td style={styles.td}>
                    <button style={styles.deleteButton} onClick={() => handleDelete(light.id)}>
                      Delete
                    </button>
                  </td>
                </tr>
              ))
            ) : (
              <tr>
                <td style={styles.td} colSpan="6">No street lights found for this location.</td>
              </tr>
            )}
          </tbody>
          </table>
        </main>
      </div>
      <footer style={styles.footer}>
        <p>Street Light Management System</p>
      </footer>
    </div>
  );
};

export default Dashboard;

It still doesn’t filter the values by location. How do I do that?

Tried to print the lights with the location selected from the drop down menu but end up getting all the lights

Dynamically expand a 12 col grid

I have 2 rows consisting of 12 cols
and a test button which should expand the first col of first row after each click.

HTML and CSS:

<div class="row">
  <div class="col"></div>
  <!-- 12 times -->
</div>
<div class="row">
  <div class="col"></div>
  <!-- 12 times -->
</div>

.row {
  display: flex;
  margin: 20px;
}

.col {
  display: flex;
  flex: 1 1 calc((100% / 12);
  position: relative;
  border: 1px dashed darkgray;
  border-right: 0;
  padding: 10px;
}

This is how I am expanding the column (when clicking the button):

const minColWidthPercentage = (1 / 12) * 100;

expandCol(col) {
  const colStyle = window.getComputedStyle(col);
  const flexBasis = parseFloat(colStyle.flexBasis) + minColWidthPercentage;
  col.style.setProperty("flex", `1 1 calc(${flexBasis}%)`);
}

As soon as I comment out the ‘padding: 10px;’ from col’s css, everything works fine.
The right border of the expanded column correctly aligns with the border of the column below from the second row.
But if I keep the padding, the alignment breaks.

Without padding after expanding 4 times:
enter image description here

With padding after expanding 4 times:
enter image description here

I already tried 1 1 calc(${flexBasis}%+${padding*n}px) approach.
But this does not solve the problem.
I think I should include the padding somehow in the percentage calculation, but how exactly?

PS: Note that, while expanding I am removing the neighbour column in another function.

Cache a Shopify Storefront Api Response with Workbox

Shopify exposes a storefront api to query data for headless e-commerce sites. The api is graphql based and every query in graphql is a POST request.

If the following url exists to query the storefront api:

https://some-store.myshopify.com/api/2024-01/graphql.json

A sample usage for a single product query would look like this

fetch('https://some-store.myshopify.com/api/2024-01/graphql.json', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Shopify-Storefront-Access-Token': '84178bc7c741a43bcg7c64308dbc6691'
  },
  body: JSON.stringify({
    query: `{
      product(id: "1") {
        title
        price
      }
    }`

  })
})

I have a setup with workbox like this, note the third argument 'POST'. According to the worbox docs for routing

All routes by default are assumed to be for GET requests.
If you would like to route other requests, like a POST request, you need to define the method when registering the route, like so:

import {registerRoute} from 'workbox-routing';

registerRoute(matchCb, handlerCb, 'POST');
registerRoute(new RegExp('/api/.*\.json'), handlerCb, 'POST');

I have the RegExp route setup and included the third parameter and I get an error in the console anyways attempt-to-cache-non-get-request: Unable to cache ‘https://some-store.myshopify.com/api/2024-01/graphql.json’ because it is a ‘POST’ request and only ‘GET’ requests can be cached

import { registerRoute } from 'workbox-routing'

registerRoute(
  /^https://headless-test-dev.myshopify.com/api/2024-01/graphql.json/,
  new NetworkFirst({
    cacheName: 'storefront-api'
  }),
  'POST'
)

If anyone can explain what I am doing wrong here it would be great.

How do I get the modal dialog box to display customized with two different buttons?

So I am working on the TicTacToe game for the Odin Project. I have two different create Player buttons that I want to open the same modal dialog box so I can enter in two different parameters and have one save across both.When I put X as the marker for one player I want it to be (required?) inaccessible for the other player, so that the other player has to pick O.How do I do this?

HTML

<body>
    <header> TIC-TAC-TOE</header>
    <section id="large-container">
        <article class="Players" id="1">
            Player1
            <button id="1">
                Enter Player
            </button>
        </article>
        <div class="container">
            <div class="item"><button id="0">0</button></div>
            <div class="item"><button id ="1">1</button></div>
            <div class="item"><button id="2">2</button></div>
            <div class="item"><button id="3">3</button></div>
            <div class="item"><button id="4">4</button></div>
            <div class="item"><button id="5">5</button></div>
            <div class="item"><button id="6">6</button></div>
            <div class="item"><button id="7">7</button></div>
            <div class="item"><button id="8">8</button></div>
        </div>
        <article class="Players" id="2">
            Player2
            <button id="2">
                Enter Player
            </button>
        </article>
        <dialog class="PlayerDialog">
            <form>
                <p>
                    <label for="playerName">What is the Player's Name</label>
                    <input type="text" id="PName" name="PName">

                    <label for="playerMarker">What is the Players marker?
                        <select>
                            <option value="X" id="X" name="Marker">X</option>
                            <option value="O" id="O" name="Marker">O</option>
                        </select>
                    </label>
                </p>
                <button value="cancel" formmethod="dialog">Cancel</button>
                <button id="Confirm" value="default">Confirm</button>
            </form>
        </dialog>
    </section>
    <script src="Main3.js"></script>
</body>

JS

const playerCreationButtons = document.querySelectorAll(".Players > button")
const playerCreation = document.querySelector(".PlayerDialog")
const PlayerDisplay = document.querySelector("article.Players")
const confirmBtn = document.querySelector("#Confirm")
const playerName = document.getElementById("#PName")
const playerMarkerX = document.getElementById("X")
playerCreationButtons.forEach((button)=>{
    button.addEventListener("click", ()=>{
         /// (Some code here to alter the modal for each player before it's shown)///
        playerCreation.showModal()
        console.log(`${button.id}`)
    })
})

“Uncaught InternalError: too much recursion” when using Javascript’s standard string.includes( ) method

In Javascript, I am getting a “too much recursion” error in Firefox and Chrome when attempting to perform the following (simplified example):

const results = [];

for (let i = 0; i < 1000; i++) {
   if ("alksdhflasdkhflsakdhflksadjflkdsahf".includes(searchQueryStrippedQuotes)) {
      results.push("match");
   }
}

I get no error when using a short string for searchQueryStrippedQuotes, even there is a large number of results to parse through (bump 1,000 here to 30,000, for instance). However, with a long string (more than 6 or 7 words), I get the error.

JavaScript Query Google Sheets API To Retrieve All Sheets

I have the following code to query a single sheet (Sheet1) from a google sheet document. Haven’t been able to find any documentation on how to query all sheets from the file

const GoogleSpreadsheet = require('google-spreadsheet');
const { google } = require("googleapis");
const spreadsheetId = '123456';

const auth = new google.auth.GoogleAuth({
    keyFile: "credentials/sheets_token.json",
    scopes: "https://www.googleapis.com/auth/spreadsheets",
});


const client = await auth.getClient();
const googleSheets = google.sheets({ version: "v4", auth: client });

const res = await googleSheets.spreadsheets.values.get({
    auth,
    spreadsheetId: spreadsheetId,
    range: 'Sheet1'
});

Tried using empty range, or excluding range parameter, or using range “Sheet1:Sheet10” none worked. Also tried fetching all sheets from the metadata, but you can only get various sheets’ titles not their rows data

How to activate bootstrap dropdown menu item by pressing keyboard key

Bootstrap 5 navbar contains dropdown menus.
Dropdown menus have underlined hotkeys like a,n,s,e :

<div class="btn-group">
  <button type="button" class="btn btn-danger dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
    Action
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#"><u>A</u>ction</a></li>
    <li><a class="dropdown-item" href="#">A<u>n</u>other action</a></li>
    <li><a class="dropdown-item" href="#"><u>S</u>omething else here</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">S<u>e</u>parated link</a></li>
  </ul>
</div>

How to activate menu item if key is pressed in keyboard? For example, if dropdowns menu is open, pressing A should act like Action menu item is clicked.

jsfiddle: https://jsfiddle.net/b6or2s5e/

Left and right arrows are already handled using

How to use left and right arrow keys to navigate in bootstrap navbar

document.addEventListener("DOMContentLoaded", function () {
  document.querySelectorAll('.dropdown').forEach(function (el) {
    el.addEventListener('shown.bs.dropdown', function () {
      document.addEventListener('keydown', function (e) {
        const click = new MouseEvent("click", {
          bubbles: true,
          cancelable: true,
          view: window,
        })
        if (e.key === "ArrowRight") {
          const o = getNextSibling(e.target.closest('.dropdown'), '.dropdown')
          if (!o) {
            document.querySelector('.dropdown-toggle').dispatchEvent(click)
          } else {
            o.querySelector('.Xdropdown-toggle').dispatchEvent(click)
          }
        } else if (e.key === "ArrowLeft") {
          const o = getPrevSibling(e.target.closest('.dropdown'), '.dropdown')
          if (!o) {
            const ar = document.querySelectorAll('.dropdown-toggle')
            ar[ar.length - 1].dispatchEvent(click)
          } else {
            o.querySelector('.dropdown-toggle').dispatchEvent(click)
          }
        }
      }, { once: true })
    })
  })
})

How to add hotkey handling also?

antibotbrowser / puppeteer + change IP by Tor

I’m currently working on a Puppeteer-based script where I want to use Tor to rotate IP addresses dynamically. The code works when I manually set up Tor for simple Puppeteer instances, but I’m having issues integrating it into my full program, which includes puppeteer-extra, puppeteer-extra-plugin-stealth, and antibotbrowser.

My goal is to automatically switch IP addresses using Tor or another proxy service every time a new page is loaded, or after a specific task is completed (like processing a set of links). I’ve implemented a function that randomly selects a Tor port and sets the proxy server for Puppeteer, but the IP address does not seem to change as expected in the context of the full program.

Here’s the relevant portion of my code:

const antibotbrowser = require("antibotbrowser");
const puppeteer = require('puppeteer-extra');
const puppeteerExtraPluginStealth = require('puppeteer-extra-plugin-stealth');
const ac = require('@antiadmin/anticaptchaofficial');...

ac.setAPIKey('afdfdbdf89489fbd4bfd');
const ipLogFile = 'ip_log.txt';
 
async function switchTorCircuit() {
  
  const socksPorts = [9050, 9052, 9053, 9054];
  
  const socksPort = socksPorts[Math.floor(Math.random() * socksPorts.length)];  
  return `socks5://127.0.0.1:${socksPort}`;
}

async function createBrowserWithTorAndAntibot() {  
  
  const proxyServer = await switchTorCircuit();
  
  puppeteer.use(puppeteerExtraPluginStealth());
  const antibrowser = await antibotbrowser.startbrowser();

  const browser = await puppeteer.connect({
    browserWSEndpoint: antibrowser.websokcet,
    args: [
      `--proxy-server=${proxyServer}`,  // Use the selected SOCKS proxy
      '--disable-features=site-per-process',
      '--no-sandbox',
      '--disable-setuid-sandbox',
    ],
    headless: false,
  });

  const page = await browser.newPage();

   // check ip ...
  
  return { browser, page };
}


(async () => {  
  const { browser, page } = await createBrowserWithTorAndAntibot();   

  await page.goto('https://www.xxx');  
  await processPage(page);
...
})();

torrc:
`
SocksPort 9050
SocksPort 9052
SocksPort 9053
SocksPort 9054

MaxCircuitDirtiness 10
NewCircuitPeriod 15

ControlPort 9051
CookieAuthentication 1`

Now I can’t change IP at all.

The API key doesn’t fit 🙂

javascript: can not set cookies with some names

javascript: can not set cookies with some names:

Chrome devtool console

> document.cookie
  (empty)

> document.cookie='clientDeviceId=123'
  (no error, but cookie was not added)

> document.cookie
   (empty)

> document.cookie='clientDeviceId2=123'
  (cookie added successfully)

> document.cookie
  'clientDeviceId2=123'

Is “clientDeviceId” a reserved name?

Same for clientSecretKey. Renaming it to
clientSecretKey2 works.

Player score remains zero in rock, paper, scissors

I have this implementation of rock, paper, scissors, where I use buttons with images for the user to indicate their choice.

But the player score won’t go up — it remains 0, no matter what. The computer score works just fine. I only have trouble with getting the player score right. What am I doing wrong?

let result;
let playerScore = 0;
let computerScore = 0;
let playerSelection;
const buttonBox = document.querySelector(".selections");
const buttons = document.querySelectorAll('button');
const roundsBox = document.querySelector(".rounds");
const selection = ["ROCK", "PAPER", "SCISSORS"];
const pScore = document.querySelector("#playerScore");
const cScore = document.querySelector("#compScore");

buttons.forEach((button) => {
  button.addEventListener('click', () => {
    playerSelection = selection.data-selection;
    playRound(computerSelection());
    game();
  });
});

const computerSelection = function () {
  return selection[Math.floor(Math.random() * 3)];
};

function playRound(computerSelection) {
  const h1 = document.createElement("h1");
  const oneRound = document.createElement("div");
  oneRound.classList.add("oneRound");
  if (playerSelection == computerSelection) {
    h1.textContent = "DRAW";
  } else if (playerSelection == "ROCK" && computerSelection == "SCISSORS") {
    h1.textContent = "WIN";
    playerScore += 1;
  } else if (playerSelection == "PAPER" && computerSelection == "ROCK") {
    h1.textContent = "WIN";
    playerScore += 1;
  } else if (playerSelection == "SCISSORS" && computerSelection == "PAPER") {
    h1.textContent = "WIN";
    playerScore += 1;
  } else {
    h1.textContent = "LOSE";
    computerScore += 1;
  }
  
  pScore.textContent = playerScore;
  cScore.textContent = computerScore;
}

function game() {
  const finalResult = document.createElement("div");
  finalResult.classList.add("rounds");
  if (playerScore != 5 && computerScore != 5) {
    return
  } else if (playerScore == 5) {
    finalResult.textContent = "YOU WON! :D";
  } else if (computerScore == 5) {
    finalResult.textContent = "YOU LOST! :(";
  }
  roundsBox.prepend(finalResult);
  buttonBox.replaceWith(finalResult);
}
<div class='selections'>
    <button class='selection' data-selection='rock'> <img alt="rock" src='images/rock.png'> </button>
    <button class='selection' data-selection='paper'> <img alt="paper"  src='images/paper.png'> </button>
    <button class='selection' data-selection='scissors'> <img alt="scissors"  src='images/scissors.png'> </button>
</div>
<div class='results'>
    <div>
        <pre><h1>Player <span id="playerScore">0</span> - <span id="compScore">0</span> Computer</h1></pre>
        <div class="rounds">First to 5 wins!</div>
    </div>
</div>

Using RTK Query with a store that contains parent keys

I work for a large company that has an in-house framework that’s built in React. We import the framework and build our application on top of it. They generate the Redux store on their end, and combine reducers that we send them in a specific file. Once the store is generated, it looks like:

{
  stuff: {
           myReducer:{}
         },
  moreStuff: {},
  theirStuff: {}
}

I was trying to use RTK Query for an API we are building, but it’s putting the reducer for the query under the ‘stuff’ key, and this is causing the query to persist in the pending state. After all my testing, it seems that RTK Query doesn’t work when the reducers are a child in the store? Is there an option to handle this?

I commented everything out and created store locally in our code, and the queries worked just fine. Unfortunately, in order to use their components, we have to use their generated store.

Async/Await not working correctly for custom version of Promise.allSettled in NodeJs

I am working on custom implementation of Promise.allSettled in NodeJs. When I implement using Promise.then it works perfectly. But when I implement using Async/Await it throw the error.

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason “Failed”.] {
code: ‘ERR_UNHANDLED_REJECTION’
}.

function myCustomAllSettled2(promises){
    return new Promise(async (resolve, reject) => {
        try{
            let completedCount = 0
            let results = []
            for(let i=0; i<promises.length; i++){
                try{
                    let result = await promises[i]
                    results[i] = {"status": "fulfilled", "value": result}
                }
                catch(ex){
                    results[i] = {"status": "rejected", "reason": ex.message || ex}
                }
                finally{
                    completedCount += 1
                    if(completedCount === promises.length){
                        resolve(results)
                    }
                }
            }  
        }
        catch(ex){
            reject(ex)
        }    
    })
};

function myCustomAllSettled(promises){
    return new Promise((resolve, reject) => {
        let completedCount = 0
        let results = []
        for(let i=0; i<promises.length; i++){
            promises[i].then(result => {
                results[i] = {"status": "fulfilled", "value": result}
            }).catch(ex => {
                results[i] = {"status": "rejected", "reason": ex.message || ex}
            }).finally(() => {
                completedCount += 1
                if(completedCount === promises.length){
                    resolve(results)
                }
            })
        }        
    })
};

(async()=>{
    try{
        let s = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('Success')
            }, 400)
        })
        
        let f = new Promise((resolve, reject) => {
            setTimeout(() => {
                reject('Failed')
            }, 300)
        })

        let promises = [s,f]
        //This works well
        myCustomAllSettled(promises).then(results => {
            results.forEach(result => {
                if(result.status === 'fulfilled'){
                    console.log('Success : ' , result.value)
                }
                else{
                    console.log('Failed : ' , result.reason)
                }
            });
        })

        let s2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('Success')
            }, 400)
        })
        
        let f2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                reject('Failed')
            }, 300)
        })
        let promises2 = [s2,f2]
        //This throws error
        let results = await myCustomAllSettled2(promises2)
        results.forEach(result => {
            if(result.status === 'fulfilled'){
                console.log('Success : ' , result.value)
            }
            else{
                console.log('Failed : ' , result.reason)
            }
        });
    }
    catch(ex){
        console.log(ex)
    }
})();

I tried implementing using Promise.then and it worked. But When I try to implement using async/await it throws error.

Replacing a deleted Landsat 5 dataset in Google Earth Engine ‘LANDSAT/LT05/C01/T1’ for 2012 NDVI calculation

I’m trying to calculate NDVI for 2012 within my study area in GEE. I believe the best available quality is Landsat 5, and when I’m trying to filter the Image Collection with this function:
“var landsatCollection = ee.ImageCollection(‘LANDSAT/LT05/C01/T1’)”, a notification pops up that it’s a deleted Landsat dataset.
This is my entire code:

// Filter the image collection based on region and date range
var Filtered_Region = ImageCollection.filterBounds(Region);
var startDate = '2012-04-01';
var endDate = '2012-05-15';

// Function to calculate NDVI for Landsat 5 images
function calculateNDVI(image) {
  var ndvi = image.normalizedDifference(['B4', 'B3']).rename('NDVI'); // B4: NIR, B3: Red
  return image.addBands(ndvi);
}

// Filter Landsat 5 image collection for the given date range and region
var landsatCollection = ee.ImageCollection('LANDSAT/LT05/C02/T1')
  .filterBounds(Region)
  .filterDate(startDate, endDate)
  .map(calculateNDVI);

// Get the median NDVI image over the date range
var medianNDVI = landsatCollection.select('NDVI').median();

// Define visualization parameters
var visParams = {
  min: -1,
  max: 1,
  palette: ['blue', 'white', 'green']
};

// Add the NDVI layer to the map with a custom name
Map.addLayer(medianNDVI, visParams, 'NDVI 2012');

// Print the NDVI image to the console for additional information
print('Median NDVI Image:', medianNDVI);

I’ve tried changing it to ‘LANDSAT/LT05/C02/T1_L2’ or ‘LANDSAT/LT05/C02/T1’, but these appear not to be working (the layer has no bands to visualise).

Is there a reason I can’t collect data from my nested React form

I am working on a NextKs app, currently working on a component that has a form. Some of the key/value pair on the form are nested (please see the code below). I was under the impression that I can traverse down element on the form, but somehow getting errors

import React from "react";

const Rafce = () => {
  const [formData, setFormData] = useState({
    title: "",
    objectives: "",
    demographic: {
      geographic: {
        country: "",
        state: "",
        city: "",
      },
      target: "",
      gender: "",
      age: "",
      intention: "",
    },
    campaignReason: "",
    strategy: "",
  });


  const items = [
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    
  ];

  const profession = ["Yes|No", "Yes", "No"];

  //Handling Country selection
  const [countries, setCountries] = useState([]);
  const [states, setStates] = useState([]);
  const [cities, setCities] = useState([]);

  const [selectedCountry, setSelectedCountry] = useState("");
  const [selectedState, setSelectedState] = useState("");
  const [selectedCity, setSelectedCity] = useState("");

  useEffect(() => {
    setCountries(Country.getAllCountries());
  }, []);

  useEffect(() => {
    if (selectedCountry) {
      setStates(State.getStatesOfCountry(selectedCountry));
      setCities([]); // Reset cities when country changes
    }
  }, [selectedCountry]);

  useEffect(() => {
    if (selectedState) {
      setCities(City.getCitiesOfState(selectedCountry, selectedState));
    }
  }, [selectedState, selectedCountry]);

  const handleCountryChange = (event) => {
    setSelectedCountry(event.target.value);
    setSelectedState("");
    setSelectedCity("");
  };

  const handleStateChange = (event) => {
    setSelectedState(event.target.value);
    setSelectedCity("");
  };

  const handleCityChange = (event) => {
    setSelectedCity(event.target.value);
  };

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData({
      ...formData,
      [name]: value,
    });
  };


  return (<div>
  <form onSubmit={handleSubmit}>
      <div className="space-y-12">
        <div className="grid grid-cols-1 gap-x-8 gap-y-10 border-b border-gray-900/10 pb-12 md:grid-cols-3">
          <div>
            <h2 className="text-base font-semibold leading-7 text-gray-900">
              Some Name
            </h2>
          </div>

          <div className="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6 md:col-span-2">
            <div className="col-span-full">
              <label
                htmlFor="title"
                className="block text-sm font-medium leading-6 text-gray-900"
              >
               Company Title
              </label>
              <div className="mt-2">
                <div className="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-red-600 sm:max-w-md">
                  <input
                    type="text"
                    name="title"
                    id="title"
                    value={formData.title}
                    onChange={handleChange}
                    className="block flex-1 w-full border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
                    placeholder="Your organization name"
                  />
                </div>
              </div>
            </div>
            
            <div className="relative inline-block text-left z-50 col-span-full">
              <select
                value={selectedItem}
                onChange={(e) => setSelectedItem(e.target.value)}
              >
                <option value="Select Type" disabled>
                  Select  Type
                </option>
                {items.map((item, index) => (
                  <option key={index} value={item}>
                    {item}
                  </option>
                ))}
              </select>
            </div>
            <div className="col-span-full">
              <label
                htmlFor="objectives"
                className="block text-sm font-medium leading-6 text-gray-900"
              >
                Objectives
              </label>
              <div className="mt-2">
                <textarea
                  id="objectives"
                  name="objectives"
                  value={formData.objectives}
                  onChange={handleChange}
                  rows={3}
                  className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-red-600 sm:text-sm sm:leading-6"
                  defaultValue={""}
                  placeholder="What are the specific goals of the campaign beyond just raising funds? (e.g., increasing awareness, engaging new donors)"
                />
              </div>
            </div>
            <div className="col-span-full">
              <label
                htmlFor="features"
                className="block text-sm font-medium leading-6 text-gray-900"
              >
                Defining demographics
              </label>
              <div className="mt-2">
                <div className="isolate -space-y-px rounded-md shadow-sm">
                  <div className="relative rounded-md rounded-t-none px-3 pb-1.5 pt-2.5 ring-1 ring-inset ring-gray-300 focus-within:z-10 focus-within:ring-2 focus-within:ring-red-600">
                    <label
                      htmlFor="feature02"
                      className="block text-xs font-medium text-gray-900"
                    >
                      Geographic location
                    </label>
                    <div className="mb-3">
                      <label
                        className="block text-xs font-medium text-gray-900"
                        htmlFor="country"
                      >
                        Country:{" "}
                      </label>
                      <select
                        id="country"
                        value={selectedCountry}
                        onChange={handleCountryChange}
                      >
                        <option
                          className="block text-xs font-medium text-gray-900"
                          value=""
                        >
                          Select Country
                        </option>
                        {countries.map((country) => (
                          <option key={country.isoCode} value={country.isoCode}>
                            {country.name}
                          </option>
                        ))}
                      </select>
                    </div>

                    {states.length > 0 && (
                      <div className="mb-3">
                        <label
                          className="block text-xs font-medium text-gray-900"
                          htmlFor="state"
                        >
                          State:{" "}
                        </label>
                        <select
                          id="state"
                          value={selectedState}
                          onChange={handleStateChange}
                        >
                          <option
                            className="block text-xs font-medium text-gray-900"
                            value=""
                          >
                            Select State/Region
                          </option>
                          {states.map((state) => (
                            <option key={state.isoCode} value={state.isoCode}>
                              {state.name}
                            </option>
                          ))}
                        </select>
                      </div>
                    )}
                    {cities.length > 0 && (
                      <div className="mb-3">
                        <label
                          className="block text-xs font-medium text-gray-900"
                          htmlFor="city"
                        >
                          City:{" "}
                        </label>
                        <select
                          id="city"
                          value={selectedCity}
                          onChange={handleCityChange}
                        >
                          <option
                            className="block text-xs font-medium text-gray-900"
                            value=""
                          >
                            Select City
                          </option>
                          {cities.map((city) => (
                            <option key={city.name} value={city.name}>
                              {city.name}
                            </option>
                          ))}
                        </select>
                      </div>
                    )}
                  </div>
                  <div className="relative rounded-md rounded-t-none px-3 pb-1.5 pt-2.5 ring-1 ring-inset ring-gray-300 focus-within:z-10 focus-within:ring-2 focus-within:ring-red-600">
                    <label
                      htmlFor="target"
                      className="block text-xs font-medium text-gray-900"
                    >
                      Target
                    </label>
                    <input
                      type="text"
                      name="target"
                      id="target"
                      value={formData.demographic.target}
                      onChange={handleChange}
                      className="block w-full border-0 p-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
                      placeholder="e.g: Gen Z, Baby Boomers, Gen X"
                    />
                  </div>
                  <div className="relative rounded-md rounded-t-none px-3 pb-1.5 pt-2.5 ring-1 ring-inset ring-gray-300 focus-within:z-10 focus-within:ring-2 focus-within:ring-red-600">
                    <label
                      htmlFor="gender"
                      className="block text-xs font-medium text-gray-900"
                    >
                      Gender
                    </label>
                    <input
                      type="text"
                      name="gender"
                      id="gender"
                      value={formData.demographic.gender}
                      onChange={handleChange}
                      className="block w-full border-0 p-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
                      placeholder="E.g: 'Male' or 'Female' "
                    />
                  </div>
                  <div className="relative rounded-md rounded-t-none px-3 pb-1.5 pt-2.5 ring-1 ring-inset ring-gray-300 focus-within:z-10 focus-within:ring-2 focus-within:ring-red-600">
                    <label
                      htmlFor="age"
                      className="block text-xs font-medium text-gray-900"
                    >
                      Age
                    </label>
                    <input
                      type="text"
                      name="age"
                      id="age"
                      value={formData.demographic.age}
                      onChange={handleChange}
                      className="block w-full border-0 p-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
                      placeholder="e.g: 20-64"
                    />
                  </div>
                  <div className="relative rounded-md rounded-b-none px-3 pb-1.5 pt-2.5 ring-1 ring-inset ring-gray-300 focus-within:z-10 focus-within:ring-2 focus-within:ring-red-600">
                    <label
                      htmlFor="intention"
                      className="block text-xs font-medium text-gray-900"
                    >
                     Intention
                    </label>
                    <input
                      type="text"
                      name="intention"
                      value={formData.demographic.intention}
                      onChange={handleChange}
                      id="intention"
                      className="block w-full border-0 p-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
                      placeholder="e.g: Events"
                    />
                  </div>
                </div>
              </div>
            </div>
            <div className="col-span-full">
              <label
                htmlFor="features"
                className="block text-sm font-medium leading-6 text-gray-900"
              >
                Strategy
              </label>
              <div className="mt-2">
                <div className="isolate -space-y-px rounded-md shadow-sm">
                  <div className="relative rounded-md rounded-b-none px-3 pb-1.5 pt-2.5 ring-1 ring-inset ring-gray-300 focus-within:z-10 focus-within:ring-2 focus-within:ring-red-600">
                    <label
                      htmlFor="feature01"
                      className="block text-xs font-medium text-gray-900"
                    >
                      What strategies have you tried
                    </label>
                    <div className="flex justify-between">
                      <Select
                        label=""
                        placeholder="Click to Select (multiple if needed)"
                        selectionMode="multiple"
                        className="bg-white"
                      >
                        {strategies.map((selection) => (
                          <SelectItem className="bg-white" key={selection.key}>
                            {selection.label}
                          </SelectItem>
                        ))}
                      </Select>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div className="mt-6 flex items-center justify-end gap-x-6">
        <button
          type="submit"
          className="rounded-md bg-green-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600"
        >
          Save and Continue
        </button>
      </div>
    </form>
  </div>);
};

export default Rafce;

The issue is that nested elements (e.g: demographic) are not showing in the UI – As if I never set the event target value. Also, the Select bitton elements that are supposed to be a simple Yes/No aren’t showing