How can I concatenate or append sorting variables to search URLs?

This is a followup to my earlier question How can I get tabbed site and image search results using Google Programmable Search?

I’m now trying to add date and sort parameters to the two URLs as variables that retrieve the search results. One URL retrieves web results for the web tab, the other image result for the images tabs. With the output of the Select dropdown onchange event, I need to append the sorting parameters to the two search and image URLs and reload them both.

This is the select dropdown

<select id="selectsort" onchange="selectthesort()">
    <option value="">Sorted by relevance</option>
    <option value="&sort=date">Sort by date</option>
    <option value="&dateRestrict=d14&sort=date">Last two weeks by date</option>
</select>

that by default option value (Sort by relevance) does not append to the URLs, since search results are by default already sorted by relevance by Google.

But for the other two options, I need to append either &sort=date to the URL when “Sort by date” is selected, or &dateRestrict=d14&sort=date when “Last two weeks by date” is selected, to each of these two URL variables:

One is for the web tab:
jsElm.src = "https://www.googleapis.com/customsearch/v1?key=key&cx=cx&start="+start+"&q="+query+"&callback=hndlr";

And this one is for the Images tab:
jsElmIM.src = "https://www.googleapis.com/customsearch/v1?key=key&cx=cx&start="+start+"&q="+query+"&searchType=image&callback=hndlrimages";

I.e. I need to do this:

When “Sort by date” is selected, append &sort=date to the jsElm.src URL
jsElm.src = "https://www.googleapis.com/customsearch/v1?key=key&cx=cx&start="+start+"&q="+query+"&callback=hndlr";

to get this:

jsElm.src = "https://www.googleapis.com/customsearch/v1?key=key&cx=cx&start="+start+"&q="+query+"&callback=hndlr&sort=date";

And append the same to the jsElmIM.src URL.

I’ve already got

var sortoptions;
function selectthesort(){
sortoptions = document.getElementById('selectsort').value;
console.log(sortoptions);
}

and that outputs the strings I need to append to the two search URLs.

Would I concatenate variables? Or append? Or use some other method?

And then how do I “fire” the URL to update/reload?

html canvas renders long streaks in image

html canvas consistently adds ‘streak’ artifacts to loaded images when it tries to render images where width is considerably longer than height.

In my case, I am using a jpeg image whose dimensions are x: 42577, y: 903, 1.5MB and loading it normally to an html canvas.

But when the image is displayed in canvas it always adds long streaks to the image starting at about 75% of the way across, all the way to the end of the image. I have tried this with many different image of approximately the same dimensions and it always does this:
bad canvas render

I assumed the image might be too large so I scaled it down considerably. It seems at any size this image is rendered with the same streaks starting in about the same place.

This is one sample jpg image that creates this problem in canvas:
sample bad image

<html>

<canvas id="myCanvas" width="1000" height="100"/>

<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
const canvasWidth = 1000;
const image = new Image();
image.src = `long-alphabet.jpg`;  // sample bad image from above above

image.addEventListener("load", (e) => {

    let width = image.width;
    let height = image.height;
        
    // Calculate the new dimensions while maintaining aspect ratio
    if (width > canvasWidth) {
        height *= canvasWidth / width;
        width = canvasWidth;
    }
  ctx.drawImage(image, 0, 0, width, height);
});
</script>


</html>

The above code, when used with the sample bad image (or any image of similar dimensions) renders this: canvas renders weird streaks

I’m getting a 403 status code when using my service principal access token to call the Users.GetUserArtifactAccessAsAdmin API

I’m trying to use a service principal to call the Users.GetUserArtifactAccessAsAdmin API in .NET.

I can obtain the access token for the service principal, but when I make the API call, I receive a 403 ( ) status code. Apparently this is due to insufficient permissions, but I’m not sure what I’m missing.

According to the API documentation, the following permissions are required:

  • Permissions: The user must be a Fabric administrator or authenticate using a service principal. Delegated permissions are supported.

  • Required Scope: Tenant.Read.All or Tenant.ReadWrite.All

But I’ve already configured the required API permissions in Azure AD under App Registrations for the service principal:
Permissions

This is how I’m getting the access token on C#

/// <summary>
/// Obtains the Access Token for service principal
/// </summary>
/// <param name="scopes"></param>
/// <returns>The access token of the service principal</returns>
/// <exception cref="Exception"></exception>
public static string GetServicePrincipalAccessToken(string[] scopes)
{
    string authority = $"https://login.microsoftonline.com/{ConfigurationManager.AppSettings["servicePrincipalTenant"]}/v2.0";
    var appConfidential = ConfidentialClientApplicationBuilder.Create(servicePrincipalId)
        .WithClientSecret(servicePrincipalSecret)
        .WithAuthority(new Uri(authority))
        .Build();

    try
    {
        AuthenticationResult authResult = appConfidential.AcquireTokenForClient(scopes).ExecuteAsync().Result;
        return authResult.AccessToken;
    }
    catch (MsalServiceException ex)
    {
        throw new Exception("Error acquiring token for the service principal.", ex);
    }
    catch (Exception ex)
    {
        throw new Exception("Unexpected error acquiring token for the service principal.", ex);
    }
}

And this how I make the call later on javascript

async function getUserArtifactAccess(userId) {
    const endpoint = `${globals.powerBiApi}/admin/users/${userId}/artifactAccess`;

    try {
        const response = await $.ajax({
            type: "GET",
            url: endpoint,
            headers: {
                "Authorization": `Bearer ${loggedInUser.servicePrincipalAccessToken}`
            },
            contentType: "application/json; charset=utf-8"
        });

        console.log("User access:", response);
        return response;
    } catch (error) {
        console.error("Error - Power BI API:", error);
        throw error;
    }
}

The variable loggedInUser contains

const loggedInUser = {
    // user access token
    accessToken: undefined,
    // service principal access token
    servicePrincipalAT: undefined,
};

Is there a way to show hover at multiple x locations for a plotly graph in R? Also, how to make changes to the y and tick marks?

I am using plotly for R and plotting a stacked plot for a common x variable and multiple y variables, each having their own y axis. Currently, the graph shows the all the y variable hover values for a particular x value.

  1. I would like to show the hover values at another x value, while the previous hover is also visible.

  2. How can I make changes to the y ranges of the stacked plot to show more ticks?

I have the following code below

Create a function for a stacked plot

plotly_stacked <- function(df, x_colName, cols){
      
      DF <- df[, cols] %>%
        tidyr::gather(variable, value, -x_colName ) %>%
        transform(id = as.integer(factor(variable)))
    
      DF$variable<- factor( DF$variable, levels = unique( DF$variable))
      
      p <- plot_ly(data = DF, x = ~get(names(DF[1])) , y = ~value, color = ~variable, colors = "Dark2",
                   yaxis = ~paste0( "y",sort(id, decreasing = F))) %>%
        
        add_lines() %>%
        layout(
         xaxis = list(
           title = ""), 
          legend = list(
                  orientation = "h",   
                  xanchor = "center",  
                  x = 0.5)) %>%
        plotly::subplot(nrows = length(unique(DF$variable)), shareX = TRUE)
      
      return(p)
    }
    

Create a data frame

df <- data.frame(
      Time = c(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,
               1,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2),
      a = c(0.01,0.02,0.03,0.04,0.05,0.06,0.07,
            0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,
            0.19,0.2),
      b = c(0.001,0.002,0.003,0.004,0.005,0.006,
            0.007,0.008,0.009,0.01,0.011,0.012,0.013,0.014,0.015,
            0.016,0.017,0.018,0.019,0.02),
      c = c(1e-04,2e-04,3e-04,4e-04,5e-04,6e-04,
            7e-04,8e-04,9e-04,0.001,0.0011,0.0012,0.0013,0.0014,
            0.0015,0.0016,0.0017,0.0018,0.0019,0.002)
    )
 

json code for making the hover appear for all variables at the same time

#Create a vector of labels
labels <- c("xy", paste0("xy", 2: 2)) # for 4 y variables, change this from 2:4


# Convert the labels to a JSON array
labels_json <- jsonlite::toJSON(labels)

# Define the JavaScript function
js_code <- sprintf(
  'function(el, x){el.on("plotly_hover", function(d) {
    Plotly.Fx.hover(el.id, {xval: d.xvals[0]}, %s);
  })}',
  labels_json
)

Plot the variables

plotly_stacked(df, "Time",  c( "Time" ,"a", "b", "c"))|>
  layout(hovermode = "x") |>
  htmlwidgets::onRender(js_code)

using map event handler for dynamically imported data massively slows down the page

I have a leaflet map with a few hundred markers on it. The markers are clustered with the markercluster plugin, and the data for the markers is loaded with a dynamic import depending on the user’s language.

These markers get filtered by tags and a search field (that works), and I want them to also be filtered by what part of the map is currently in view (I’m outputting a list of all the results in HTML). To this end I have a function updateFiltering(points) that takes an array of markers as a parameter.

I want to call this function whenever the map is done moving, whether that’s from panning or zooming. I’m doing it like this:

let sth = 
  import('./data-'+lang+'.js')
    .then((langdata) => {
      updateCheckboxStates();
      addMarkers(pFilter(langdata.points));
      updateFiltering(langdata.points);
      const points = langdata.points;

      map.on('moveend', function(e) {
        updateFiltering(points);
      });
    })
    .catch((error) => {
      console.error(error);
    });

This works, but after a bit of zooming around it slows the page down immensely, to the point where the browser prompts me to stop the script. The console said ‘too much recursion’ at one point – that explains the massive delay, but I don’t understand why that’s happening?

If I use an event on the markercluster layer, for example

      markers.on('animationend', function(e) {
        updateFiltering(points);
      });

– this works alright (but doesn’t catch all the use cases). But any event handler attached to map slows the page down.

I’m really grateful for any advice!

Node & Express Backend deploy on Varcel

I am new in the backend. I need Help.

Here is the problem: using node.js & express.js I want to deploy the full-stack web application I just built with MERN stack. I have developed the server side with the help of ChatGPT & my knowledge.

I have checked the backend & it is working fine in my local system & also successfully connected with MongoDB.

Now, I want to deploy the server for free so I choose varcel. I saw a couple of videos on YT but it didn’t work.

Can anyone Help me out with how I can deploy a server in Varcel?

My project file structure if this helps –

>To-do
 >backend
  >node_modules
  >.gitignore
  >index.js
  >package-lock.json
  >package.json
  >varcel.json
 >frontend

Here is the plan I got from YT & I followed so far:

created varcel.json file inside my backend root directory since varcel needs this file-

{
    "version":2,
    "builds": [{"src":"./index.js","use":"@vercel/node"}],
    "routes": [{"src":"/(.*)", "dest": "/"}]
}

my index.js that I have developed-

    const express = require("express");
    const mongoose = require("mongoose");
    const bodyParser = require("body-parser");
    const cors = require("cors");
    
    const app = express();
    const PORT = 3001;
    
    app.use(cors(
      {
        origin: ["YT videos says paste here frontend deployment link"],
        methods:["GET","POST","DELETE","PUT"],
        credentials: true
      }
    ));
    
    // Middleware
    app.use(bodyParser.json());
    app.use(cors());
    
    // Connect to MongoDB
    const MONGO_URI = "deleted, since this is sensitive data";
    mongoose.connect(MONGO_URI)
    .then(() => console.log("MongoDB connected"))
    .catch(err => console.error("MongoDB connection error:", err));
    
    // Define Task Schema
    const taskSchema = new mongoose.Schema({
      text: { type: String, required: true },
      completed: { type: Boolean, default: false },
    });
    
    const Task = mongoose.model("Task", taskSchema);
    
    //Basic API checking
    app.get("/",async (req, res) => {
      res.json("Hello, API is working !!");
    });

// Start the server
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Now YT videos say that I have to deploy this backend part differently & the production link will be my APIs. Later I have to deploy the frontend part & also need to update API call URLs in the code. But for me, it is not working.

Since I am not getting the default response from the varcel production server, there is no need to check from the frontend right? Once I get that response, I’ll be sure that my backend is working fine with varcel.

So is there any solution for this?

navigator.geolocation.watchPosition does not use gps (any alternatives ?)

I’m trying to access the user’s location on my webpage, but the location I get is very imprecise and does not use GPS. I have already checked the permissions in my browser (Firefox) and system (Android 14).

To be more precise, I can get an accurate GPS location, but only if it is cached from another app that used GPS just seconds before. The web browser itself does not seem to be able to use GPS directly.

navigator.geolocation.watchPosition(
      (position) => {
            if (position.coords.accuracy <= 100){
                lat = position.coords.latitude;
                lon = position.coords.longitude;
            }
            displayCoordinates(lat, lon, position.coords.accuracy);
      },
      (error) => {
          console.error("Geolocation error:", error);
      },
      {
          enableHighAccuracy: true,
          timeout: 10000,
          maximumAge: 0
      }
  );

When I open the site, I am asked to enable location. After that, I receive my location with an accuracy of 120–200 meters, which I assume is from cellular data and not GPS because, in other apps, I can get GPS accuracy down to 3 meters. Also, the icon in the top left corner of the screen, which indicates when GPS is being used, never appears.

All this indicates that navigator.geolocation.watchPosition simply accepts any position provided by the system or browser and does not activate the GPS.

Is there a better method that can turn on the GPS and obtain a precise location on majority of modern devices?

My Notes component is not working properly [closed]

A screenshot of the Notes app's bug
So I am making an application for storing Notes and an technical bug or glitch came where I can edit the notes , nor do anything with it. Can you help me please. Additionally, the codes are also available on my GITHUB. But here is the concise version of it.

Notes.jsx:

import React, { useContext } from 'react';
import { useState, useEffect, useRef } from "react";
import AddNotes from './AddNotes';
import NoteItem from './NoteItem';
import { useNotes } from '../../hooks/NotesProvider';


const Notes = () => {
  const context = useNotes();
  const { notes, getNotes, editNote } = context;
  useEffect(() => {
      getNotes();
  }, []);
  const ref = useRef(null);
  const refClose = useRef(null);
  const [note, setNote] = useState({id: "", etitle: "", econtent: "", etag: ""});

  const updateNote = (currentNote) => {
    ref.current.click();
    setNote({id: currentNote._id, etitle: currentNote.title, econtent: currentNote.content, etag:currentNote.tag});
  }

  const handleClick = (e) => {
    editNote(note.id, note.etitle, note.econtent, note.etag);
    refClose.current.click();
  }

  const onChange = (e) => {
    setNote({...note, [e.target.value]:e.target.value});
  }

  return (
    <>
        <AddNotes />
        <button ref={ref} type="button" className="btn btn-primary d-none" data-bs-toggle="modal" data-bs-target="#exampleModal">
            Launch demo modal
        </button>
        <div className="modal fade" id="exampleModal" tabIndex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
            <div className="modal-dialog">
                <div className="modal-content">
                    <div className="modal-header">
                        <h5 className="modal-title" id="exampleModalLabel">Edit Note</h5>
                        <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div className="modal-body">
                        <form className="my-3">
                            <div className="mb-3">
                                <label htmlFor="title" className="form-label">Title</label>
                                <input type="text" className="form-control" id="etitle" name="etitle" value={note.etitle} aria-describedby="emailHelp" onChange={onChange} minLength={5} required/>
                            </div>
                            <div className="mb-3">
                                <label htmlFor="description" className="form-label">Description</label>
                                <input type="text" className="form-control" id="edescription" name="edescription" value={note.edescription} onChange={onChange} minLength={5} required/>
                            </div>
                            <div className="mb-3">
                                <label htmlFor="tag" className="form-label">Tag</label>
                                <input type="text" className="form-control" id="etag" name="etag" value={note.etag} onChange={onChange} />
                            </div>

                        </form>
                    </div>
                    <div className="modal-footer">
                        <button ref={refClose} type="button" className="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                        <button disabled={note.etitle.length<5 || note.edescription.length<5} onClick={handleClick} type="button" className="btn btn-primary">Update Note</button>
                    </div>
                </div>
            </div>
        </div>

        <div className="row my-3">
            <h2>You Notes</h2>
            {notes?.map((note) => {
                return <NoteItem key={note.id} updateNote={updateNote} note={note} />
            })}
        </div>
    </>
)
}

export default Notes;

NoteItem.jsx:

import React from "react";
import { useNotes } from "../../hooks/NotesProvider";
const NoteItem = (props) => {
  const context = useNotes();
  const { deleteNote } = context;
  const { note, updateNote } = props;
  return (
    <div>
      <a
        href="#"
        className="block max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow-sm hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700"
      >
        <h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
          {note.title}
        </h5>
        <i
          className="far fa-trash-alt mx-2"
          onClick={() => {
            deleteNote(note._id);
          }}
        ></i>
        <i
          className="far fa-edit mx-2"
          onClick={() => {
            updateNote(note);
          }}
        ></i>
        <p className="font-normal text-gray-700 dark:text-gray-400">
          {note.content}
        </p>
      </a>
    </div>
  );
};

export default NoteItem;

AddNotes.jsx:

import React, { useContext } from "react";
import { useState, useEffect } from "react";
import { useNotes } from "../../hooks/NotesProvider";

const AddNotes = () => {
  const context = useNotes();
  const { addNote } = context;
  const [note, setNotes] = useState({ title: "", content: "", tag: "" });

  const handleClick = (e) => {
    e.preventDefault();
    addNote(note.title, note.content, note.content);
    setNotes({ title: "", content: "", tag: "" });
  };

  const onChange = (e) => {
    setNotes({ ...note, [e.target.value]: e.target.value });
  };

  return (
    <div>
      <form class="max-w-sm mx-auto">
        <div class="mb-5">
          <label
            for="title"
            class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
          >
            Title
          </label>
          <input
            type="title"
            id="title"
            class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            placeholder="[email protected]"
            required
            value={note.title}
            onChange={onChange}
          />
        </div>
        <div class="mb-5">
          <label
            for="content"
            class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
          >
            Content
          </label>
          <input
            type="content"
            id="content"
            class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            required
            value={note.content}
            onChange={onChange}
          />
        </div>
        <div class="mb-5">
          <label
            for="tag"
            class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
          >
            Tag
          </label>
          <input
            type="tag"
            id="tag"
            class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            required
            value={note.tag}
            onChange={onChange}
          />
        </div>
        <button
          type="submit"
          class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
          onClick={handleClick}
        >
          Submit
        </button>
      </form>
    </div>
  );
};

export default AddNotes;

hooks/NotesProvider.js:

import { createContext, useContext, useState } from "react";

const NotesContext = createContext();

const NotesProvider = ({children}) => {
    const notesInitial = [];
    const [notes, setNotes] = useState(notesInitial);
    
    const getNotes = async(data) => {
        try{
            const response = await fetch("http://localhost:5000/api/auth/register",{
                method: "GET",
                headers:{
                    "Authorization": `Bearer ${localStorage.getItem("site")}`,
                },
                body: JSON.stringify(data),
            });
            const res = await response.json();
            if(res){
                console.log(res);
                setNotes(res.data);
                return;
            }
            throw new Error(res.message);
        }catch(err){
            console.error(err);
        }
    };

    const addNote = async(title, content, tag) => {
        try{
            const response = await fetch('http://localhost:5000/api/notes/create-note',{
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${localStorage.getItem("site")}`,
                },
                body: JSON.stringify({title, content, tag})
            });
            const res = await response.json();
            if(res){
                setNotes(res.data);
                return;
            }
            throw new Error(res.message);
        }catch(err){
            throw new Error(err.message);
        }
    }

    const editNote = async(id, title, content, tag) => {
        try{
            const response = await fetch(`http://localhost:5000/api/notes/update-note/${id}`,{
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${localStorage.getItem("site")}`,
                },
                body: JSON.stringify({ title, content, tag})
            });
            const json = await response.json();
            
            let newNotes = JSON.parse(JSON.stringify(notes));
            if (newNotes && newNotes.length) {
                for (let index = 0; index < newNotes.length; index++) {
                    const element = newNotes[index];
                    if (element._id === id) {
                        newNotes[index].title = title;
                        newNotes[index].content = content;
                        newNotes[index].tag = tag;
                        break;
                    }
                }
            } else {
                console.error('newNotes is not defined or is empty');
            }            
            setNotes(newNotes);
        }catch(err){
            throw new Error(err.message);
        }
    }

    const deleteNote = async(id) => {
        try{
            const response = await fetch(`http://localhost:5000/api/notes/delete-note/${id}`,{
                method: "DELETE",
                headers:{
                    "Authorization": `Bearer ${localStorage.getItem("site")}`,
                }
            });
            const res = await response.json();
            if(res){
                const newNotes = notes.filter((note) => {return note._id !== id});
                setNotes(newNotes);
            }
        }catch(err){
            throw new Error(err.message);
        }
    }
    return (
        <NotesContext.Provider value={{ notes, addNote, deleteNote, editNote, getNotes }}>
          {children}
        </NotesContext.Provider>
    )
};


export default NotesProvider;

export const useNotes = () => {
    return useContext(NotesContext);
};

toggle button doesn’t close when is clicked

I have a navigation bar in bootstrap and my problem is that the toggle button doesn’t close when ,only opens.I’m looking for hours to fix it but nothing happens.I show you tow html files .In The index.html something conflicts and doesn’t work whereas in file contact.html it works.

index.html

 <!DOCTYPE html>

ArtShop Original & Prints;

<!-- vendor css files -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<link rel="stylesheet" href="mystyle.css">
<link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet">


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"
    integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
    crossorigin="anonymous"></script>



<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
    crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"
    integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy"
    crossorigin="anonymous"></script>
<!--  -->

<!-- cdn fontawesome -->
<script src="https://kit.fontawesome.com/ce111f8d46.js" crossorigin="anonymous"></script>



<script>

    // Show caption on hover 
    let position_relative =
        document.querySelectorAll('.position-relative');

    position_relative.forEach(item => {
        item.addEventListener('mouseover', event => {
            const caption = item.querySelector('.position-absolute');
            caption.classList.remove('d-none');
        });
        item.addEventListener('mouseleave', event => {
            const caption = item.querySelector('.position-absolute');
            caption.classList.add('d-none');
        });
    });
</script>


<!-- carousel  -->

<div class="container-fluid">

    <div id="carouselExampleInticators" class="carousel slide" data-bs-ride="carousel" data-bs-interval="100">
        <div class="carousel-inner">
            <div class="carousel-item active c-item" data-bs-interval="1500">
                <img src="https://images.unsplash.com/photo-1520420097861-e4959843b682?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTR8fHBhaW50aW5nJTIwY2FudmFzfGVufDB8fDB8fHww"
                    class="d-block w-100 c-img" alt="slide 1">
                <div class="carousel-caption d-flex flex-column h-100 align-items-center justify-content-center">
                    <p class="mt-5 fs-3 text-uppercase">Welcome</p>
                    <h1 class="display-1 fw-bolder text-capitalize">The Cre-Art</h1>
                    <button type="button" id="btn-carousel" class="btn btn-default  px-7 py-2 fs-8 mt-5"
                        data-bs-toggle="modal" data-bs-target="#booking-modal">VIEW FULL COLLECTION</button>

                </div>
            </div>
            <div class="carousel-item c-item" data-bs-interval="1500">
                <img src="https://plus.unsplash.com/premium_photo-1673514503009-912ffc6ff956?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTN8fGxhbmRzY2FwZSUyMHBhaW50aW5nfGVufDB8fDB8fHww"
                    class="d-block w-100 c-img" alt="slide 2">
                <div class="carousel-caption d-flex flex-column h-100 align-items-center justify-content-center">
                    <p class="mt-5 fs-3 text-uppercase">Welcome</p>
                    <h1 class="display-1 fw-bolder text-capitalize">DISCOVER MY COLLECTION</h1>
                    <button type="button" id="btn-carousel" class="btn btn-default  px-7 py-2 fs-8 mt-5 ">VIEW FULL
                        COLLECTION</button>

                </div>
            </div>
            <div class="carousel-item c-item" data-bs-interval="1500">
                <img src="https://plus.unsplash.com/premium_photo-1673470370451-6a60e9d93127?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8cGFpbnRpbmclMjBicnVzaHxlbnwwfHwwfHx8MA%3D%3D"
                    class="d-block w-100 c-img" alt="slide 3">
                <div class="carousel-caption d-flex flex-column h-100 align-items-center justify-content-center">
                    <p class="mt-5 fs-3 text-uppercase">An artworld different from the usual</p>
                    <h1 class="display-1 fw-bolder text-capitalize">TRUST THE PROCESS OF CREATING</h1>
                    <button type="button" id="btn-carousel" class="btn btn-default  px-7 py-2 fs-8 mt-5 ">VIEW FULL
                        COLLECTION</button>

                </div>
            </div>
        </div>
        <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators"
            data-bs-slide="prev">
            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Previous</span>
        </button>
        <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators"
            data-bs-slide="next">
            <span class="carousel-control-next-icon" aria-hidden="true"></span>
            <span class="visually-hidden">Next</span>
        </button>
    </div>
</div>


<!-- end of carousel -->


<div class="container justify-content-center" style="margin-top: 50px;">
    <p class="text-center">This collection is not just a series of paintings—it’s a glimpse into the untamed
        landscapes and intimate
        moments that speak of resilience, discovery, and the serenity we find in nature.</p>
    <h3 class="text-center" style="margin-top: 40px;">Each piece is a window to the calm, inviting you to pause and
        breathe deeply.</h3>
    <h1 class="text-center" style="margin-top: 40px;">EXPERIENCE THE HIGHLANDS AT HOME</h1>
</div>
<div class="container px-4" style="margin-top: 50px;">
    <div class="row ">
        <div class="col-md-4">
            <div class="thumbnail">
                <img src="https://media.istockphoto.com/id/502426696/photo/beautiful-seascape.webp?a=1&b=1&s=612x612&w=0&k=20&c=ogFnp8AiUtFWg_XS4KyXaCKlIyfkipTdoe0RAfmXWvw="
                    alt="one" class="img-fluid" style="width:100%">
                <div class="caption">
                    <p>6x8" Oil Painting - ‘Colliding Horizons’
                        <br> £120.00
                    </p>
                </div>
            </div>
        </div>
        <div class="col-md-4">
            <img src="https://media.istockphoto.com/id/524301691/photo/crimean-war-cape-aiya.webp?a=1&b=1&s=612x612&w=0&k=20&c=HVa1B5OWAIbZXkwSk2vhybcdYp1k9DQVH4XoM5uu6A0="
                alt="two" class="img-fluid" style="width:100%">
            <div class="caption">
                <p>30x40" Oil Painting - ‘Momentary’
                    <br> £150.00
                </p>
            </div>
        </div>
        <div class="col-md-4">
            <img src="https://media.istockphoto.com/id/1192160498/photo/watercolor-illustration-of-seascape-horizon-at-sunset.webp?a=1&b=1&s=612x612&w=0&k=20&c=pGfHVtDhjuoK6hWCTzP_34J__49H4x7QGAhDDMzmKac="
                alt="three" class="img-fluid" style="width:100%">
            <div class="caption">
                <p>8x8" Acrylic Painting - ‘Morning Calm’
                    <br> £180.00
                </p>
            </div>
        </div>

    </div>
</div>


<div class="container " style="margin-top: 50px;">
    <div class="row justify-content-md-center ">
        <div class=" col-md-8 offset-md-4">
            <img src="https://media.istockphoto.com/id/1277460281/photo/male-painter-at-art-studio-indoors-in-the-process-of-painting-pensive.webp?a=1&b=1&s=612x612&w=0&k=20&c=PhQjFpNLWO93XM98bgDRkLeyyCoOlM3s53WKvtrJWR0="
                alt="" class="img-fluid" style="width: 900px; height:500px;">
        </div>

        <div class="container" style="background-color: rgb(178, 192, 185); width: 600px; height:500px"
            id="overtheimg">
            <div class="row justify-content-md-center">
                <div class="col">
                    <h1 style="margin-top: 50px;">BRING THE SALTY SEA AIR INDOORS</h1>
                    <p style="line-height: 30px;">My ocean collection “The Sea & it’s Rhythm” has been curated to
                        bring the
                        cleansing & serene
                        qualities of the ocean to your space. Take a deep breath and relax into these subtle hues of
                        blue.
                    </p>
                    <button type="button" id="btn-explore" class="btn btn-default">EXPLORE OCEANS</button>


                </div>
            </div>
            <!-- <h1 style="margin-top: 50px;">BRING THE SALTY SEA AIR INDOORS</h1>
            <p style="line-height: 30px;">My ocean collection “The Sea & it’s Rhythm” has been curated to bring the
                cleansing & serene
                qualities of the ocean to your space. Take a deep breath and relax into these subtle hues of blue.
            </p>
            <button type="button" id="btn-explore" class="btn btn-default">EXPLORE OCEANS</button> -->
        </div>
    </div>
</div>

<div class="container-behindtheeasel d-flex align-items-center justify-content-center" style="margin-top: -250px;">
    <div class="bkgd-image"></div>
    <div class="text-content">

        <h2 class="fst-italic ms-1">Who's behind the easel</h2><br>
        <h1>HI I'M EVITA</h1><br>
        <h2 class="fst-italic">artist,Web & Graphic designer</h2><br>
        <p class="lh-base">I enjoy creating dreamy impressionist paintings in oils and
            acrylics. My art is deeply influenced by the beauty and serenity of nature, and my aim is to document
            the way it makes me feel onto canvas. <br>I believe all of us are creative individuals and I’m
            passionate about helping others gain confidence in painting. </p>
        <button type="button" id="btn-visitmystudio" class="btn btn-default">VISIT MY STUDIO</button>
    </div>
</div>

<div class="container" id="studio-stories">
    <article>
        <h1 class="text-center my-4 text-black">STUDIO STORIES</h1>

        <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4 g-3 row ">
            <div class="col">
                <div class="position-relative gallery-item" style="cursor: pointer;">
                    <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                        alt="" class="w-100">
                    <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                        <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                            HTML
                        </div>
                    </div> -->
                </div>

            </div>

            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>

            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>

            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>

            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>

            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>
            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>

            <div class="col">
                <img src="https://media.istockphoto.com/id/1139826864/photo/smiling-young-afro-woman-holding-color-palette-and-paintbrush.webp?a=1&b=1&s=612x612&w=0&k=20&c=3wK4C1oGAxcg3142PNLvmja6bccbaEb0kET8xHLn9Gc="
                    alt="" class="w-100">
                <!-- <div class="position-absolute top-50 
        start-50 translate-middle 
        text-center d-none">
                    <div class="bg-success bg-opacity-70
            text-white px-4 py-2">
                        HTML
                    </div>
                </div> -->

            </div>

        </div>

    </article>

</div>


<!-- welcome container -->

<div class="container-welcome">

    <div class="row justify-content-center">

        <div class="col-4">
            <h1 style="margin-bottom: 40px;">Welcome to my Art Studio</h1>
            <p>This is my online bussiness store with the name "The Cre-Art".The history behind of this ,is the
                combination of two words "Create" and "Art".Creating art was always my passion and with a
                magical way, a
                safe place where I was feeling inspired and good of myself!!Selling online handmade products
                with full
                of love offering satisfaction and happiness each one of you!!
            </p>
            <h2></h2>
        </div>
        <div class="col-4">
            <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTJigcdmEAUqY-2CAZn9_zzRMcU0jiEX4CBhg&s"
                alt="welcome-art-studio" class="welcome-pic">
        </div>
    </div>

</div>
<!-- end welcome container -->



<div class="container-fluid" id="socialmedia">

    <h1 class="text-center text-white">Watch my channel on Youtube</h1>
    <h3 class="text-center text-white">#tutorials</h3>
    <div class="container" id="gallery-item-socialmedia">

        <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 row-cols-xl-4 g-3 ">
            <div class="col-sm-6" id="youtubeborder">
                <div class=" bg-image hover-overlay shadow-1-strong rounded " data-mdb-ripple-init
                    data-mdb-ripple-color="light" style="cursor: pointer;">

                    <a href="https://youtu.be/pu7_hIhkAIM?si=MZEmKl55ZJPdpowN" target="_blank" class="thumbnail">
                        <div class="img">
                            <i class="fa fa-play-circle-o fa-4x"></i>
                            <img src="./images/thumbnails/thumbnail-Trust your instict.png" alt="" class="w-100" />
                        </div>
                        <div class="mask" style="background-color: hsla(0, 11%, 87%, 0.2)"></div>
                    </a>

                </div>
            </div>

            <div class="col-sm-6" id="youtubeborder">
                <div class="position-relative gallery-item" style="cursor: pointer;">
                    <a href="https://youtu.be/fWMxsYczvXg?si=J0X50eZLhYXj8DOp" target="_blank" class="thumbnail">
                        <div class="img">
                            <i class="fa fa-play-circle-o fa-4x"></i>
                            <img src="./images/thumbnails/thumbnail -youtube ups&downs.png" alt="" class="w-100" />
                        </div>
                        <div class="mask" style="background-color: hsla(0, 11%, 87%, 0.2)"></div>
                    </a>

                </div>

            </div>
            <div class="col-sm-6" id="youtubeborder">
                <div class="position-relative gallery-item" style="cursor: pointer;">
                    <a href="https://youtu.be/fntbKyA-iNQ?si=NxT9F-AK3hXUNxoA" target="_blank" class="thumbnail">
                        <div class="img">
                            <i class="fa fa-play-circle-o fa-4x"></i>
                            <img src="./images/thumbnails/thumbnail youtube GIFT.png" alt="" class="w-100" />
                        </div>
                        <div class="mask" style="background-color: hsla(0, 11%, 87%, 0.2)"></div>
                    </a>

                </div>
            </div>
            <div class="col-sm-6" id="youtubeborder">
                <div class="position-relative gallery-item" style="cursor: pointer;">
                    <a href="https://youtu.be/uE7Sm8b8H6o?si=iIbITtZURG4SllBv" target="_blank" class="thumbnail">
                        <div class="img">
                            <i class="fa fa-play-circle-o fa-4x"></i>
                            <img src="./images/thumbnails/thumbnail youtube tutorial.png" alt="" class="w-100" />
                        </div>
                        <div class="mask" style="background-color: hsla(0, 11%, 87%, 0.2)"></div>
                    </a>

                </div>


            </div>

        </div>
    </div>
</div>



<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

contact.html

<!DOCTYPE html>

ArtShop Original & Prints; Evita Zacharioudaki

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
    crossorigin="anonymous"></script>
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css"> -->
<script src="https://kit.fontawesome.com/ce111f8d46.js" crossorigin="anonymous"></script>


<link rel="stylesheet" href="mystyle.css">
<!-- <script src="https://code.jquery.com/jquery-1.10.2.js"></script> -->
<script src="//code.jquery.com/jquery.min.js"></script>
<!--Navigation bar-->
<div id="nav-placeholder">

</div>

<script>
    $(function () {
        $("#nav-placeholder").load("nav.html");
    });
</script>
<!--end of Navigation bar-->


          
<div class="contact3 py-5">
    <div class="row no-gutters">
        <div class="container">
            <div class="row">
                <div class="col-lg-6">
                    <div class="card-shadow">
                        <img src="images/me.jpg" class="img-fluid">
                    </div>
                </div>
                <div class="col-lg-6">
                    <div class="contact-box ml-3">
                        <h1 class="font-weight-light mt-2">I'D LOVE TO HEAR FROM YOU</h1>
                        <p class="lead">Reach out to me if you have any questions.Don't hesitate to ask me anything
                        </p>
                        <form class="mt-4">
                            <div class="row">
                                <div class="col-lg-5">
                                    <div class="form-group mt-2">
                                        FulName<input class="form-control" type="text" >
                                    </div>
                                </div>
                                <div class="col-lg-5">
                                    <div class="form-group mt-2">
                                        Email<input class="form-control" type="email" >
                                        <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
                                    </div>
                                </div>
                                <div class="col-lg-5">
                                    <div class="form-group mt-2">
                                        
                                        Phone<input class="form-control" type="text">
                                    </div>
                                </div>
                                <div class="col-lg-10">
                                    <div class="form-group mt-2">
                                        message<textarea class="form-control" rows="3" ></textarea>
                                    </div>
                                </div>
                                <div class="col-lg-12">
                                    <button type="submit"
                                        class="btn btn-danger-gradiant mt-3 text-white border-0 px-3 py-2"><span>
                                            SUBMIT</span></button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
                <div class="col-lg-13">
                    <div class="card-contact mt-4 border-0 mb-4">
                        <div class="row">
                            <div class="col-lg-4 col-md-4">
                                <div class="card-body d-flex align-items-center c-detail pl-0">
                                    <div class="mr-3 align-self-center">
                                        <img
                                            src="https://www.wrappixel.com/demos/ui-kit/wrapkit/assets/images/contact/icon1.png">
                                    </div>
                                    <div class="">
                                        <h6 class="font-weight-medium">Address</h6>
                                        <p class="">Heraklion
                                            <br> Crete,Creece
                                        </p>
                                    </div>
                                </div>
                            </div>
                            <div class="col-lg-4 col-md-4">
                                <div class="card-body d-flex align-items-center c-detail">
                                    <div class="mr-3 align-self-center">
                                        <img
                                            src="https://www.wrappixel.com/demos/ui-kit/wrapkit/assets/images/contact/icon2.png">
                                    </div>
                                    <div class="">
                                        
                                        <div>
                                            <h6 class="font-weight-medium">Phone</h6>
                                            <p class="">6941539795
                                                <br> 2811113697
                                            </p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="col-lg-4 col-md-4">
                                <div class="card-body d-flex align-items-center c-detail">
                                    <div class="mr-3 align-self-center">
                                        <img
                                            src="https://www.wrappixel.com/demos/ui-kit/wrapkit/assets/images/contact/icon3.png">
                                    </div>
                                    <div class="">
                                        <h6 class="font-weight-medium">Email</h6>
                                        <p class="">[email protected]
                                            <br> [email protected]
                                        </p>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>



<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Showing different divs on different days of the year

I find writing php and javascript hard, but okay with basic coding. I wonder if someone could help.

I am looking to have multiple of different parent div to show only on different days of a year. So on 10th February one will show and then disappear at the end of the day, and 12th March another one will show and disappear at the end of the day.

Could anyone help me? Please

How to Synchronize Clerk Users with Prisma ORM in a React Application?

I am building a React application that uses Clerk for authentication and Prisma ORM to manage users in my database. I want to ensure that users in Clerk are automatically synced with my database when they are:

Created (user.created)
Updated (user.updated)
Deleted (user.deleted)

Current Setup:

I have implemented a webhook in my Express backend to handle user.created events and store new users in Prisma:

/* eslint-disable no-undef */
import express from 'express';
import { Webhook } from 'svix';
import dotenv from 'dotenv';
import cors from 'cors';
import bodyParser from 'body-parser';
import { PrismaClient } from '@prisma/client';

dotenv.config();

const app = express();
const prisma = new PrismaClient();
const PORT = process.env.PORT || 3000;

app.use(cors());
app.use(bodyParser.json());

const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET;

if (!WEBHOOK_SECRET) {
  console.error('Missing Clerk Webhook Secret!');
  process.exit(1);
}

app.post('/webhook/clerk', async (req, res) => {
  const svix_id = req.headers['svix-id'];
  const svix_timestamp = req.headers['svix-timestamp'];
  const svix_signature = req.headers['svix-signature'];

  if (!svix_id || !svix_timestamp || !svix_signature) {
    return res.status(400).json({ error: 'Missing Svix headers' });
  }

  const payload = req.body;
  const body = JSON.stringify(payload);

  try {
    const wh = new Webhook(WEBHOOK_SECRET);
    const evt = wh.verify(body, {
      'svix-id': svix_id,
      'svix-timestamp': svix_timestamp,
      'svix-signature': svix_signature
    });

    if (evt.type === 'user.created') {
      const { id, email_addresses, first_name, last_name, image_url } = evt.data;

      if (!id || !email_addresses || email_addresses.length === 0) {
        return res.status(400).json({ error: 'Invalid user data' });
      }

      await prisma.user.create({
        data: {
          clerkUserId: id,
          email: email_addresses[0].email_address,
          firstName: first_name || null,
          lastName: last_name || null,
          imageUrl: image_url || null
        }
      });

      console.log(`User ${id} created.`);
    }

    res.status(200).json({ success: true });
  } catch (error) {
    console.error('Error processing webhook:', error);
    res.status(400).json({ error: 'Webhook verification failed' });
  }
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

I tried to connect Clerk’s webhook to my aplication using ngrok as it mentioned in the documentation: https://clerk.com/docs/webhooks/sync-data
I configured the end point in the clerk dashboard, but there was still an error.
I received 403 (forbidden) from ngrok tunnel. In Clerk documentation I have not found any giude for react installation.

Need a rough idea and the possible react libraries to implement a grid-based drag and drop [closed]

I am building an app for a school project. On my landing page, there will be screen full of widgets (think of the IOS layout). The requirements are:

  1. The widgets are arranged in a grid like manner with equal spacing
  2. When you resize the screen width, the widget size is constant. Rather, the grid items rearranges itself to fit the screen
  3. The widgets should have a drag and drop functionality such that I can rearrange the widgets (but it should still snap to the grid)
  4. Browser local storage should store the rearranged position, such that on reload, the widgets will render according to the last saved position

I’m planning to use dnd-kit for 3. What are some libraries I can explore to fit my requirements 1 and 2? The behaviour mimics IOS layout plus a resizable feature to it.
Thanks guys!

Why is the generic type of this class getting overwritten in JSDOC, but not Typescript?

We’re working on converting a project from Typescript (.ts) to Typescript-via-JSDOC (.js).

We have a class StateHolder, instances of which contain data described by the generic State. The data can be provided at instantiation, or later on.

Here’s a very minimal version of how it looks in Typescript, which passes type-checking and compiles without issue:

// state.ts

type StateHolderOptions = {};

class StateHolder<State> {
    value?: State;

    constructor(
        initialValue?: State,
        options: StateHolderOptions = {}
    ) {
        if (initialValue !== undefined) {
            this.value = initialValue;
        }
    }
}

type MyState = { data: string };

const state = new StateHolder<MyState>(undefined, {});

Here’s the same code as we’ve converted it into JS:

// state.js

/**
 * @typedef {object} StateHolderOptions
 */

/**
 * @template State
 */
class StateHolder {
    /**
     * @type {State | undefined}
     */
    value;

    /**
     * @param {State} [initialValue]
     * @param {StateHolderOptions} [options] - Unused
     */
    constructor(initialValue, options = {}) {
        if (initialValue !== undefined) {
            this.value = initialValue;
        }
    }
}

/**
 * @typedef {{ data: string }} MyState
 */

const state = /** @type {StateHolder<MyState>} */(new StateHolder(undefined, {}));

We thought the JS and TS were exactly equivalent. However, in the JS version the final line const state throws this type-checking error:

Conversion of type 'StateHolder<undefined>' to type 'StateHolder<MyState>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Type 'undefined' is not comparable to type 'MyState'.

We don’t get type errors if we do this, but it’s very verbose so would be nice to avoid it:

const state = new StateHolder(/** @type {MyState} */(/**  @type {unknown} */(undefined)), {});

We may be able to get the correct typing by defining it in types.d.ts but would rather do it in one file if we can.

Why do the JS and TS versions behave differently, and in JS how can we maintain the generic State while passing in undefined?