Best way to handle nested arrays in MongoDB

I am relatively new to Node.js and MongoDB, and I am working on developing a user management system for my project using Mongoose. I’ve created a basic schema for user data, but I want to make sure it’s optimized for performance as the application scales.

Here’s my current schema:

const UserSchema = new Schema(
  {
    ip: { type: String },
    wallet: { type: String },
    time_of_registration: { type: Date },
    time_of_last_reward: { type: Date, default: null },
    time_of_last_withdrawal: { type: Date, default: null },
    status: { type: Boolean, default: true },
    reward: { type: String, default: "0" },
    notifications: [
      {
        notification: { type: Schema.Types.ObjectId, ref: "Notification" },
        seen: { type: Boolean, default: false },
        sent: { type: Date, default: Date.now },
      },
    ],
    quests: [{ type: Schema.Types.ObjectId, ref: "Quest" }],
    cyclical_quests: [{ type: Schema.Types.ObjectId, ref: "Cyclical-quest" }],
    surprise: [
      {
        attached_surprise: { type: Schema.Types.ObjectId, ref: "Surprise" },
        claimed: { type: Boolean, default: false },
        claimed_at: { type: Date, default: null },
      },
    ],
    rewards: [
      {
        reward: { type: Schema.Types.ObjectId, ref: "Reward" },
        reward_quantity: { type: String, default: null },
        reward_pool: { type: String, default: null },
        withdrawal_status: { type: String, enum: ["idle", "inprogress", "done", "rejected"], default: "idle" },
        withdrawal_date: { type: Date, default: null },
        attached_at: { type: Date, default: null },
      },
    ],
  },
  {
    timestamps: true,
  }
);

would appreciate some guidance on best practices for optimizing this schema. Specifically:

  1. Are there any potential pitfalls or inefficiencies with my current design?

  2. How can I ensure that the schema remains performant as the number of records grows?

  3. Are there recommended strategies for handling nested arrays more efficiently?

I want to make sure I’m following best practices to ensure the scalability and performance of my application. Any advice, examples, or resources would be highly appreciated.

Abort pomise to stop playing soundclip

Forty years ago I programmed my own 6502 Assembly language EEPROM for my Commodore PET, and now I’m having trouble to ‘just’ implement an abort method for a promise 🙁

Made a program for the browser which has lots of text and many links (> 900) to soundclips. Clicking a link plays the sound.
All very well till I had the idea that with so many sounds I could make a kind of jukebox which would play those sounds in a loop in random sequence.
This now works fine using a promise, but sometimes I just want to skip the playing sound, so I need a way to abort the currently playing sound so that the program can pick the next sound.
I found many examples here in Stackoverflow, mostly dealing with Fetch and Timeout, I studied and tried various methods, but still I’m unable to skip to the next sound….
It probably is some ‘simple’ error, but at the moment I don’t see which line is wrong or where I have to add some more coding, so any help is appreciated !

Have the following, which is working nicely: it plays random songs in an ‘infinite’ loop, but I just can’t find the correct way to implement the abort, so that I can skip a song.

const ac = new AbortController();
…
async function jukebox({ signal } = {}) {
  var jbsong = '';      // holds the song’s filename
  var maxSongs = 5;     // set max nr of songs to play in a row
  jbplays = true;       // global that tells system that jukebox is playing
  for (var j = 0; j < maxSongs; j++) {      // loop over songs
    jbsong = getRandomSong();
    try {
      const answer = await playSound(jbsong));
    }
    catch (playerror) {
      console.log(j + ". NOT found: " + jbsong);
      console.log("PlayError: " + playerror);
    }
  }
  jbplays = false;  // indication that jukebox is not running anymore
  stopMedia();      // hide some info that was displayed
  console.log("Jukebox Finished");
};
…
function playSound(soundfile) { 
  audio.src = (soundfile);  // rest of audio was already defined
  if (jbplays) {                    // if called from julebox
    return new Promise(function(resolve, reject) {  // return a promise
      audio.onerror = reject;       // an error
      audio.onended = resolve;      // done playing 
    })
  }
  else {                // called as a normal one-song play
  … playing of a single song (by click on a link) plays OK  
  }
};  

For the time being I try to abort the promise using key S in my handleKeyboard as follows:

case 83:        //  S - Skip to next sound, so abort the promise
  if (jbplays) {     // jukebox is playing
    console.log("Now trying to abort promise");
    ac.abort();     // Doesn’t seem to do anything at the moment
  } 
  break;

Summarizing:
Play by click on a link is OK.
Play in loop is OK.
Abort the promise, so as to go to next song in the loop is not OK.
The message “Now trying to abort promise” is displayed.

What am I missing ?
Thank you very much !

Why I get Uncaught Error even after .catch()?

Here is the code:

function sleep(ms:number)
{
  return new Promise((resolve:any,reject:any) => setTimeout(resolve,ms))
}

async function errorFunc(): Promise<void>
{ 
 await sleep(2000)
 console.log("error throw")
 throw new Error("critical error");
}


let promises: Promise<void>[] = []

for(let i = 0; i < 1; i++)
{
  const promise = errorFunc();
  promise.then(()=>console.log("then"))
  promise.catch(()=> console.log("catch"))
  promises.push(promise)
}

async function main()
{
 await Promise.all(promises).catch((e)=>console.log("promise all catch"))
}

main();

Here are logs:

               error throw
runtime.ts:177 catch
runtime.ts:177 promise all catch
VM193:8 Uncaught (in promise) Error: critical error

Isn’t the catch supposed to catch an error in Promise?
And actually, error passes through all catches but still at the end “Uncaught”

JavaScript convert nested promise to async await [closed]

I’ve an function which was already written in promise

  public loadUser(): Promise<any> {
    return new Promise((resolve, reject) => {
      this.getUser().then((userResponse) => {
        if (userResponse) {
          this.getAppSupportUsersList();
          this.getUserEntitlements().then(entitlementResponse => {
            resolve(entitlementResponse);
          }).catch((error) => {
            resolve(true);
          });
        } else {
          resolve(true);
        }
      }).catch((error) => {
        resolve(true);
      });
    });
  }

I want to write in new form using async & await. I’m not sure how to convert this nested promises into async await types.

How to write test case for these functions in Jest

How to improve test case of the following function?

import { NavigateFunction } from 'react-router';

    export const setQueryArgument = (navigate: NavigateFunction, k: string, v: string): void => {
    const params = new URLSearchParams(window.location.search);
    if (params.get(k) !== v) {
      params.set(k, v);
      const url = new URL(window.location.href);
      navigate(`${url.pathname}?${params.toString()}${url.hash}`, { replace: true });
     }
    };
    
    export const removeQueryArgument = (navigate: NavigateFunction, k: string): void => {
    const params = new URLSearchParams(window.location.search);
    if (params.has(k)) {
       params.delete(k);
       const url = new URL(window.location.href);
       navigate(`${url.pathname}?${params.toString()}${url.hash}`, { replace: true });
     }
    };

I have come up with something like below

const navigate = jest.fn();
describe('setQueryArgument', () => {
  it('should set a query argument and navigate', () => {
    const key = 'param';
    const value = 'example';

    const initialUrl = new URL(window.location.href);
    initialUrl.searchParams.set(key, value);

    // Call setQueryArgument to set the query parameter
    setQueryArgument(navigate, key, value);

    // Check if navigate is called with the expected URL
    const expectedUrl = `${initialUrl.pathname}?${key}=${value}`;
    expect(navigate).toHaveBeenCalledWith(expectedUrl, { replace: true });
  });
  it('should not navigate if query argument is already set to the same value', () => {
    const key = 'param';
    const value = 'example';

    const initialUrl = new URL(window.location.href);
    initialUrl.searchParams.set(key, value);

    // Simulate an existing query parameter with the same value
    window.history.pushState({}, '', `?${key}=${value}`);
    // Call setQueryArgument to set the query parameter with the same value
    setQueryArgument(navigate, key, value);

    // Check if navigate is not called
    expect(navigate).not.toHaveBeenCalled();
  });
});
describe('removeQueryArgument', () => {
  it('should remove a query argument and navigate', () => {
    const key = 'param';

    const initialUrl = new URL(window.location.href);
    initialUrl.searchParams.set(key, 'example');

    // Call removeQueryArgument to remove the query parameter
    removeQueryArgument(navigate, key);

    // Check if navigate is called with the expected URL
    const expectedUrl = `${initialUrl.pathname}?${initialUrl.hash}`;
    expect(navigate).toHaveBeenCalledWith(expectedUrl, { replace: true });
  });

  it('should not navigate if query argument does not exist', () => {
    const key = 'nonexistent';

    const initialUrl = new URL(window.location.href);
    initialUrl.searchParams.delete(key);

    // Call removeQueryArgument to remove the non-existing query parameter
    removeQueryArgument(navigate, key);

    // Check if navigate is not called
    expect(navigate).not.toHaveBeenCalled();
  });
});

but this it('should remove a query argument and navigate', () => { relies on the setup of key param from the previous test. Tests should be setup to function in isolation. also, These lines DO NOT update window.location it only updates the initialUrl variable which is a copy.

 const initialUrl = new URL(window.location.href);
 initialUrl.searchParams.set(key, 'example');

How to get first visible character’s offset in a node

I have large paragraphs of text in <p> nodes in epub files and i’m displaying these on a mobile screen webview using an external library.

The library allows me to flip pages to see portions of these <p> node.

I can get the currently visible node from the DOM.

But i also need to get the offset of the first character that is currently visible in that node.

For Example:

enter image description here

In the above image the visible text is small portion of the actual <p> element. I want to get the character offset (not pixel offset) of first character which is “v” in this case

Is there a way to do that?

How to change tax calculation parameters at Woocoomerce checkout?

Can you help me?
In Brazil we have a very different way of calculating taxes than in other countries. He follows:
1 – If the value of the product is less than R$ 250.00

a) Add the value of the Product + Shipping;
b) Add ICMS of 17% to the previous value;
c) include the Post Office customs clearance fee, which is a fixed amount of R$ 15.00
d) Give the total sum

2 – If the value of the product is greater than R$ 250.00

a) Add the value of the Product + shipping;
b) Add the Import Tax of 60% on the previous value
c) Add the ICMS of 17% on the previous value
d) include the Post Office customs clearance fee, which is a fixed amount of R$15.00 on top of the previous amount.
e) Give the total sum

Follow the code. I do not know if it’s right. I thank everyone who can help me.

NodeJS try catch not working in development mode

I am developing my discord bot, I don’t know why this happen, the try catch works in production but not working in development.

Code inside an event listener client.on('interactionCreate', interaction => { // code below is here }):

let profilePanel = []

try {
  profilePanel = await Promise.all(
    mGenshinProfile.genshinUIDs.map(async gUID => {
      const playerData = await genshin.getPlayer(gUID)
      return await createGenshinProfilePanel(
        interaction,
        playerData,
        userId,
      )
    }),
  )
} catch (e) {
  const embed = new EmbedBuilder().setColor(theme.primary)
  embed.setTitle('Error').setDescription('Something went wrong!')
  await interaction.editReply({
    embeds: ,
  })
  await wait(5000)
  await interaction.deleteReply()
  return
}

There’s throw new error(…) in genshin.getPlayer function while the server is under maintenance.

Here’s how the error info looks like catch from client.on('error', err => {console.log(err)}):

APIError: Maintenance or everything is broken
    at RequestHandler.player (/app/node_modules/enkanetwork.js/dist/handlers/RequestHandler.js:48:19)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async GenshinClient.getPlayer (/app/node_modules/enkanetwork.js/dist/client/Genshin/GenshinClient.js:73:22)
    at async Object.execute (file:///app/src/commands/modalSubmit/Genshin/addGenshinProfileModal.ts:101:32)
    at async Client.<anonymous> (file:///app/src/listeners/interactionCreate.ts:40:17) {
  status: 424,
  path: 'https://enka.network/api/uid/824957678'
}

However in development it won’t catch the error and execute what inside catch. But funny in production it works as expected, the attachment is the proof of it works in production: production mode.

I am using docker image node:lts-alpine which is v20.11.0

I run my development with this script inside package.json:

clear && NODE_ENV=dev && node --import ./register-hooks.js --watch src/app.ts

I am expecting the error handler by try catch works in development mode.

I want to make a SendKeys from an ENTER with JavaScript to a text field of an HTML form

I am trying to send an ENTER in the “fullname” text field via a keyboard key send, i.e. a SendKeys. I can’t figure out how to do it. I would appreciate your help.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form name="formBasic">
        <p>Ingresa tu nombre completo: <input type="text" name="fullname"></p> 
        <input type="submit" value="Enviar la información">
    </form>
</body>
</html>

How do I generate a bar graph from a mysql database using google charts?

I would like to generate a graph like this using google charts js:

enter image description here

below is my data source:

enter image description here

I tried to make such a graph but it is coming out wrong. My graph comes out looking like the image below:

enter image description here

below is the code i used to implement this graph:

<?php include("db.php"); ?>
<html>
<head>
  
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    google.charts.load('current', {
      'packages': ['corechart']
    });
    google.charts.setOnLoadCallback(drawChart);

    function drawChart() {
      var data = google.visualization.arrayToDataTable([
        [ 'Q','21', '22','23','24','25', '26','27','28','29', '30','31','32','33', '34','35','36','38'],
        <?php
        $query = "select * from pirep";
        $res = mysqli_query($conn, $query);
        while ($data = mysqli_fetch_array($res)) {
          $a = $data["21"];
          $b = $data["22"];
          $c = $data["23"];
          $d = $data["24"];
          $e = $data["25"];
          $f = $data["26"];
          $g = $data["27"];
          $h = $data["28"];

          $i = $data["29"];
          $j = $data["30"];
          $k = $data["31"];
          $l = $data["32"];
          $m = $data["33"];
          $n = $data["34"];
          $o = $data["35"];
          $p = $data["36"];

          $q = $data["38"];

          $w = $data["qt"];


        ?>
          ['<?php echo $w; ?>', <?php echo $a; ?>, <?php echo $b; ?>, <?php echo $c; ?>, <?php echo $d; ?>, <?php echo $e; ?>, <?php echo $f; ?>, <?php echo $g; ?>, <?php echo $h; ?>, <?php echo $i; ?>, <?php echo $j; ?>, <?php echo $k; ?>, <?php echo $l; ?>, <?php echo $m; ?>, <?php echo $n; ?>, <?php echo $o; ?>, <?php echo $p; ?>, <?php echo $q; ?>],

        
        <?php 
      } 
      ?>
      ]);

      var options = {
        title: 'AIRCRAFT AVAILABILITY',
        // curveType: 'function',
        legend: {
          position: 'bottom'
        }
      };

      var chart = new google.visualization.BarChart(document.getElementById('curve_chart'));

      chart.draw(data, options);
    }
  </script>















</head>

<body style='background-color:#676a6d';
>
    
    <center>
    
    
    <table class="tg" style="background-color:white; margin-bottom: 20px">
        <thead>
          <tr>
            <td class="tg-0lax"> <img src="NAT.jpg" alt="Italian Trulli"> <strong> <label for="" style="margin-left: 10PX; margin-right:10px; margin-bottom:10px">AIRCRAFT AVAILABILITY & DESPATCH RELIABILITY</label></strong>   <img src="sr.jpg" alt="Italian Trulli"> </td>
            
           
              
            </tr>

           

        </th>
    </table>
  </center>
   

 
  <center><div id="curve_chart" style="width: 1000px; height: 300px; border: 1px solid black;margin-bottom:5px" ></div></center>
   
  


</center>
</body>

</html>

I am new to programming, so I apologize if my question sounds silly.

code for my database table is below:

-- phpMyAdmin SQL Dump
-- version 5.2.0
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Jan 31, 2024 at 02:57 PM
-- Server version: 10.4.24-MariaDB
-- PHP Version: 8.1.6

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `reliability`
--

-- --------------------------------------------------------

--
-- Table structure for table `pirep`
--

CREATE TABLE `pirep` (
  `id` int(255) NOT NULL,
  `qt` varchar(255) NOT NULL,
  `cyc` int(11) NOT NULL,
  `21` float NOT NULL,
  `22` float NOT NULL,
  `23` float NOT NULL,
  `24` float NOT NULL,
  `25` float NOT NULL,
  `26` float NOT NULL,
  `27` float NOT NULL,
  `28` float NOT NULL,
  `29` float NOT NULL,
  `30` float NOT NULL,
  `31` float NOT NULL,
  `32` int(11) NOT NULL,
  `33` float NOT NULL,
  `34` float NOT NULL,
  `35` float NOT NULL,
  `36` float NOT NULL,
  `38` float NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

--
-- Dumping data for table `pirep`
--

INSERT INTO `pirep` (`id`, `qt`, `cyc`, `21`, `22`, `23`, `24`, `25`, `26`, `27`, `28`, `29`, `30`, `31`, `32`, `33`, `34`, `35`, `36`, `38`) VALUES
(1, '2020 Q1', 343, 0, 0, 2.62391, 1.16618, 0, 0, 1.74927, 1.74927, 1.74927, 0.291545, 0.58309, 1, 0, 0.291545, 0, 0, 0),
(2, '2020 Q2', 326, 0, 0.306748, 1.53374, 0.613497, 0, 0, 0, 0.306748, 0.306748, 0, 0.613497, 1, 0, 0, 0, 0, 0),
(3, '2020 Q3', 225, 0, 0, 3.11111, 0, 0, 0.444444, 0.888889, 0.444444, 0.444444, 0, 0, 1, 0, 0, 0, 0, 0),
(4, '2020 Q4', 259, 0, 0, 1.5444, 0, 0, 0, 0.3861, 1.9305, 1.9305, 0, 0, 5, 0, 0, 0, 0, 0);

--
-- Indexes for dumped tables
--

--
-- Indexes for table `pirep`
--
ALTER TABLE `pirep`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `pirep`
--
ALTER TABLE `pirep`
  MODIFY `id` int(255) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

useNavigate does not replace my dynamic parameter

Sur notre project nous utilisions la v4 de react-router, nous avons fait la migration vers la v6.

En revanche nous sommes face à un problème que je n’arrive pas a identifier depuis le changement d’API de useLocation vers useNavigate

Here’s my function:

import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';

import { IProps, IPropsReturn } from './types';

export const useSteppers = ({ steppers, redirectPath }: IProps): IPropsReturn => {
  const { customerOuid, routeFeature, routeTab, step } = useParams();
  const navigate = useNavigate();
  const currentStep = step ? parseInt(step) : 0;

  useEffect(() => {
    if (!step || currentStep > steppers.length - 1) {
      navigate(`/customer/${customerOuid}/${routeTab}/${routeFeature}/0`);
    }
  }, [step]);

  const handlePrevStep = () => {
    const prevStep = currentStep - 1;

    if (currentStep === 0) {
      return navigate(-1);
    }
    return navigate(`${prevStep}`, { replace: true });
  };

  const handleSubmit = (triggerPolling: () => void) => {
    const nextStep = currentStep + 1;

    if (currentStep === steppers.length - 1 && redirectPath) {
      if (triggerPolling) {
        return triggerPolling();
      }
      return navigate(redirectPath, { replace: true });
    }

    return navigate(`${nextStep}`, { replace: true });
  };

  return {
    currentStep,
    handlePrevStep,
    handleSubmit,
  };
};

The problem is actually here :

return navigate(`${nextStep}`, { replace: true });

When the function is executed, the navigate function returns a route :

localhost:3000/#/customer/123/accounting/chargeCancellation/0/1

Do you see the problem ? 0/1 I would like only /1

Before we migrate to v6 we use :

    const history = useHistory(); 
    return history.replace(`${nextStep}`);

HTML/CSS (SCSS) – Image on top of every printing page

So, I have a small and simple page that looks like this:

Page

Normal view in the browser works perfect and everything is how I want it to have (with all the styles [margin, padding,..] etc.).


Now, My problem, or rather my question, is about the print view of this page.

As you can see in the above image, there is the “seperator”-image. The content#1 can be sometimes smaller, sometimes bigger (with texts etc.).

When content #1 is too big I want the seperator-image to show on top of the second page.

Is there somehow a way to do that? (I think javascript has to be used for this (no jquery!).


A image to show what I approximately want for the print view:

print view


I hope everything is understandable, and thanks in advance!

React: Set up axios to work with Suspense

I recently heard about React.Suspense and I wanted to use it in a new project.

To setup React.Suspense with Axios I followed this tutorial

The first request of in that project consist of checking if there is a user logged in to the app.
I checked that by sending a request /user to the API and if the API returns the user information if there is a cookie containing a JWT token otherwise it will return a 401 error

The issue is that I am having errors that I don’t understand.

Here is the code of some parts of the project, hoping that it can help you understand my issue

App.tsx

function App() {
  return (
    <BrowserRouter>
      <AxiosInstanceProvider config={{ baseURL: process.env.BACKEND_URL || "http://localhost:8080/" }}>
        <CurrentUserContextProvider>
          <Routes>
            <Route path='/' element={<LandingPage />} />
            <Route path='/auth/*' element={<AuthPage />}>
              <Route path='sign-in' element={<SignInPage />} />
              <Route path='sign-up' element={<SignUpPage />} />
            </Route>
            <Route path='/orgs' element={<ListOfOrganizationsPage />} />
          </Routes>
        </CurrentUserContextProvider>
      </AxiosInstanceProvider>
    </BrowserRouter>
  );
}

AxiosInstanceProvider

export const AxiosContext = createContext<AxiosInstance | null>(null);
export const useAxiosContext = () => useContext(AxiosContext);

interface AxiosInstanceProviderProps {
  config: CreateAxiosDefaults | AxiosRequestConfig,
  children: JSX.Element
}
export const AxiosInstanceProvider = ({
  config = {},
  children,
}: AxiosInstanceProviderProps) => {
  const instanceRef = useRef(
    axios.create({
      ...config,
      headers: {
        'Accept': 'application/json',
        "Content-Type": "application/json",
      },
      withCredentials: true
    })
  );
  const location = useLocation();
  const navigate = useNavigate();

  const redirectToSignIn = useCallback(() => {
    if (location.pathname.includes("/auth/sign-in")) return;

    navigate(`/auth/sign-in?from=${encodeURIComponent(location.pathname)}`)
  }, [location.pathname, navigate]);

  const onResponse = useCallback((response: AxiosResponse) => {
    return response;
  }, []);

  const onUnauthorizedRequest = useCallback((error: AxiosError) => {
    if (error?.response?.status === 401) {
      redirectToSignIn();

      return;
    }

    return Promise.reject(error)
  }, [redirectToSignIn]);


  useEffect(() => {
    instanceRef.current.interceptors.response.use(onResponse, onUnauthorizedRequest);
  }, [instanceRef, onResponse, onUnauthorizedRequest]);


  return (
    <AxiosContext.Provider value={instanceRef.current}>
      {children}
    </AxiosContext.Provider>
  );
}

useAxios

type RequestMethod = "GET" | "POST" | "PATCH" | "DELETE";

export class TError {
  error: string;

  constructor(message: string) {
    this.error = message;
  }
}

function wrapPromise<T>(promise: Promise<T>) {
  let status = 'pending'
  let response: T|string;

  const suspender = promise.then(
    (res: T) => {
      status = 'success'
      response = res
    },
  ).catch((err: AxiosError) => {
      console.log("an error occurent: ", err);
      status = 'error'
      response = err.response?.data as string;
    },
  )

  const read = () => {
    switch (status) {
      case 'pending':
        throw suspender
      case 'error':
        throw response
      default:
        return response
    }
  }

  return { read }
}

const useAxios = () => {
  const abortControllerRef = useRef(new AbortController());
  const contextAxiosInstance = useAxiosContext();
  const instance = useMemo(() => {
    return contextAxiosInstance || axios
  }, [contextAxiosInstance])
  const cancel = () => {
    abortControllerRef.current.abort();
  }

  const fetchApiResponse = useCallback(
    async <T,S = {}>(url: string, method: RequestMethod, data?: S) => {
      try {
        const response = await instance<T>({
          method,
          url,
          data
        })

        if (response.status >= 200 && response.status < 400) {
          return response;
        } else {
          throw new Error(response.statusText)
        }
      } catch (error) {
        return error as AxiosError;
      }
    },
    [instance]
  )

  const fetchApiData = useCallback(<T,S = {}>(url: string, method: RequestMethod, data?: S) => {
      const promise = instance<T>({
        method,
        url,
        data
      })
      .then((response) => response.data);

      return wrapPromise(promise);
    },
    [instance]
  )

  return useMemo(() => ({
    cancel,
    fetchApiResponse,
    fetchApiData
  }), [fetchApiData, fetchApiResponse]);

};

export default useAxios;

GetCurrentUser

export default function useApiAuth() {
  const { fetchApiData } = useAxios();

  const getCurrentUser = useCallback(
    () => fetchApiData<UserType>("user", "GET").read(),
    [fetchApiData]
  )

  return useMemo(
    () => ({
      getCurrentUser,
    }),
    [
      getCurrentUser
    ]
  )
}

CurrentUserContext

interface CurrentUserContextType {
  currentUser: UserType | null;
  isLoadingCurrentUser: boolean;
  setCurrentUser: (user: UserType) => void;
}
export const CurrentUserContext = createContext<CurrentUserContextType>({
  currentUser: null,
  isLoadingCurrentUser: false,
  setCurrentUser: () => {}
});
export const useCurrentUserContext = () => useContext(CurrentUserContext);

const CurrentUserContextProvider = ({ children }: CurrentUserContextProviderProps) => {
  const {currentUser, isLoadingCurrentUser, setCurrentUser} = useCurrentUser();

  return (
    <CurrentUserContext.Provider value={{currentUser, isLoadingCurrentUser, setCurrentUser}}>
      {children}
    </CurrentUserContext.Provider>
  )
}

interface CurrentUserContextProviderProps {
  children: JSX.Element
}
export default memo(({ children }: CurrentUserContextProviderProps) => {
  return (
    // <ErrorBoundary fallback={<div>Error Occurred when checking current user..</div>}>
      <Suspense fallback={<div>Checking current user ...</div>}>
        <CurrentUserContextProvider>
          {children}
        </CurrentUserContextProvider>
      </Suspense>
    // </ErrorBoundary>
  )
});

useCurrentUser

export default function useCurrentUser() {
  const [error, setError] = useState("");
  const [currentUser, setCurrentUser] = useState<UserType | null>(null);
  const [isLoadingCurrentUser, setIsLoadingCurrentUser] = useState<boolean>(true);
  const { getCurrentUser } = useApiAuth();

  useEffect(() => {
    function _getCurrentUser() {
      setIsLoadingCurrentUser(true);
      const response = getCurrentUser();
      console.log("GCUR-U : Response : ", response);
      if (response instanceof TError) {
        console.log("Response Error")
        setError(response.error);
      }
      setIsLoadingCurrentUser(false);
    }

    _getCurrentUser();
  }, [getCurrentUser, setIsLoadingCurrentUser, setError]);

  return useMemo(() => ({
    currentUser,
    setCurrentUser,
    isLoadingCurrentUser,
    error
  }), [currentUser, error, isLoadingCurrentUser]);
}

I was expecting to see the message Checking current user ... while sending the request /user to the API and then being redirect to /auth/sign-in
But I am having those errors

  • Promise {<pending>}
  • The above error occurred in the

enter image description here

Automatically Saving Email Attachments to Google Drive [closed]

i found this amazing article online, providing code on how to save email attachments online. Hoping the community can help me do some adjustment to the code, so that i can tailor the code to just save attachments to emails that are just sent out today, and not all emails attachments

https://medium.com/@pablopallocchi/automatically-save-email-attachments-to-google-drive-using-google-apps-script-7a751a5d3ac9

function saveNewAttachmentsToDrive() {
  var folderId = "PUT_YOUR_FOLDER_ID_HERE"; // Replace with the ID of the destination folder in Google Drive
  var searchQuery = "to:[email protected] has:attachment"; // Replace with the search query to find emails with attachments
  var lastExecutionTime = getLastExecutionDate();
  var threads = GmailApp.search(searchQuery + " after:" + lastExecutionTime);
  var driveFolder = DriveApp.getFolderById(folderId);
  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();
    for (var j = 0; j < messages.length; j++) {
      var message = messages[j];
      var attachments = message.getAttachments();
      for (var k = 0; k < attachments.length; k++) {
        var attachment = attachments[k];
        var attachmentBlob = attachment.copyBlob();
        var fileName = attachment.getName();
        driveFolder.createFile(attachmentBlob).setName(fileName);
      }
    }
  }
  updateLastExecutionDate();
}

function getLastExecutionDate() {
  var properties = PropertiesService.getUserProperties();
  return properties.getProperty("lastExecutionDate") || "2023-09-01";
}

function resetLastExecutionDate() {
  PropertiesService.getUserProperties().deleteProperty("lastExecutionDate");
}

function updateLastExecutionDate() {
  var now = new Date();
  var dateString = now.toISOString().split("T")[0];
  var properties = PropertiesService.getUserProperties();
  properties.setProperty("lastExecutionDate", dateString);
}

code is working, just that it downloads all attachments.

Video swapping scrolling effect on HTML JS

I am trying to replicate this video scrolling swap effect.
https://malinowskiego.com/en.

I’m not a web developer so coding is not my thing, so I am using chat gpt to help and achieve that effect, but I seem to gfet on a loop of errors, from not swapping vidoes to just ignoring other videos.

I hope you can help me, because what I have right now is, a video bg that changes on section, but I am missing that in btween transition video

This is the code that I am using so far.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Color Transition Website</title>
  <link rel="stylesheet" href="aptbg.css">
</head>
<body>

<section class="video-wrapper" id="section-1">
  <div class="video-container">
    <video id="videoBg" class="video-bg" autoplay loop muted>
      <source src="hero_1.mp4" type="video/mp4">
      Your browser does not support the video tag.
    </video>
  </div>
</section>

<section class="color-section red-section" id="section-2">
  <h1>Section 2</h1>
  <div class="rectangle"></div>
</section>

<section class="color-section blue-section" id="section-3">
  <h1>Section 3</h1>
</section>

<section class="color-section green-section" id="section-4">
  <h1>Section 4</h1>
</section>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/ScrollMagic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/plugins/animation.gsap.min.js"></script>
<script src="swapvideos.js"></script>

</body>
</html>

CSS

body {
  margin: 0;
  overflow: hidden;
}

.video-wrapper {
  height: 100vh;
  overflow: hidden;
  position: fixed;
  width: 100%;
  z-index: 1;
}

.video-container {
  position: relative;
  width: 100%;
  height: 100%;
}

.video-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
}

.color-section {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  z-index: 2;
  color: #ffffff;
  font-size: 36px;
}

.red-section {
  background-color: rgba(255, 0, 0, 0.3);
}

.blue-section {
  background-color: rgba(0, 0, 255, 0.3);
}

/* Add these styles for the green section */
.green-section {
  background-color: #00ff00;
}

.green-section h1 {
  color: #ffffff;
}

/* Ensure scrollbar is visible */
body {
  overflow-y: scroll;
}


@media only screen and (max-width: 600px) {
  .color-section {
    font-size: 24px;
  }
}

JS

document.addEventListener('DOMContentLoaded', function () {
  const videoElement = document.getElementById('videoBg');
  const videoSources = ['hero_1.mp4', 'hero_2.mp4', 'hero_3.mp4', 'hero_4.mp4'];
  const videoDurations = [4000, 1000, 4000, 1000]; // in milliseconds
  let currentVideoIndex = 0;

  function changeVideoSource(index) {
    videoElement.src = videoSources[index];
    videoElement.load();
    videoElement.play();
  }

  function handleSectionChange(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const sectionId = entry.target.id;
        handleVideoChange(sectionId);
      }
    });
  }

  function handleVideoChange(sectionId) {
    switch (sectionId) {
      case 'section-2':
        // Swap from hero_3 to hero_1 (when going back from section-3 to section-2)
        if (currentVideoIndex === 2) {
          changeVideoSource(0);
          currentVideoIndex = 0;
        }
        break;
      case 'section-3':
        // Swap from hero_1 to hero_3
        if (currentVideoIndex === 0) {
          changeVideoSource(2);
          currentVideoIndex = 2;
        }
        // Swap from hero_2 to hero_3
        else if (currentVideoIndex === 1) {
          changeVideoSource(2);
          currentVideoIndex = 2;
        }
        break;
      // Exclude Section 4
    }
  }

  const options = {
    root: null,
    rootMargin: '0px',
    threshold: 0.5,
  };

  const observer = new IntersectionObserver(handleSectionChange, options);

  // Observe the target sections
  observer.observe(document.getElementById('section-2'));
  observer.observe(document.getElementById('section-3'));

  // Play the initial video (hero_1)
  changeVideoSource(0);
});