How to show audio waveform inside the player (like Telegram voice messages) in Vue + Tailwind? [closed]

enter image description here
I’m building a call center dashboard where we need to add recorded conversations. The audio should be displayed with a waveform inside the player itself, not as a separate element. Something like this example:

Play/Pause button on the left

Duration on the right

The progress bar is replaced by a waveform visualization

Tech stack: Vue 3 + Tailwind CSS.
Requirements:

I don’t need advanced audio editing or studio-level tools

Just a simple inline waveform (like Telegram or WhatsApp voice messages)

What are some simple libraries or Vue components that can do this, or how can I achieve it?

I looked into using Wavesurfer.js, but it felt too heavy for my use case.

Crud operation using html,css and javascript [closed]

I am performing crud operation using html,css and javascript. In this while i m running the web page it’s displaying the form structure but when i am giving the input its not taking or input is not getting saved. how i should resolve this and what mistake am i making there? why my data is not stored ,without storing data i can not perform the crud operation.

var selectedRow = null

function onFormSubmit() {
    if (validate()) {
        var formData = readFormData();
        if (selectedRow == null)
            insertNewRecord(formData);
        else
            updateRecord(formData);
        resetForm();
    }
}

function readFormData() {
    var formData = {};
    formData["fullName"] = document.getElementById("fullName").value;
    formData["empCode"] = document.getElementById("empCode").value;
    formData["salary"] = document.getElementById("salary").value;
    formData["city"] = document.getElementById("city").value;
    return formData;
}

function insertNewRecord(data) {
    var table = document.getElementById("employeeList").getElementsByTagName('tbody')[0];
    var newRow = table.insertRow(table.length);
    cell1 = newRow.insertCell(0);
    cell1.innerHTML = data.fullName;
    cell2 = newRow.insertCell(1);
    cell2.innerHTML = data.empCode;
    cell3 = newRow.insertCell(2);
    cell3.innerHTML = data.salary;
    cell4 = newRow.insertCell(3);
    cell4.innerHTML = data.city;
    cell4 = newRow.insertCell(4);
    cell4.innerHTML = `<a onClick="onEdit(this)">Edit</a>
                       <a onClick="onDelete(this)">Delete</a>`;
}

function resetForm() {
    document.getElementById("fullName").value = "";
    document.getElementById("empCode").value = "";
    document.getElementById("salary").value = "";
    document.getElementById("city").value = "";
    selectedRow = null;
}

function onEdit(td) {
    selectedRow = td.parentElement.parentElement;
    document.getElementById("fullName").value = selectedRow.cells[0].innerHTML;
    document.getElementById("empCode").value = selectedRow.cells[1].innerHTML;
    document.getElementById("salary").value = selectedRow.cells[2].innerHTML;
    document.getElementById("city").value = selectedRow.cells[3].innerHTML;
}
function updateRecord(formData) {
    selectedRow.cells[0].innerHTML = formData.fullName;
    selectedRow.cells[1].innerHTML = formData.empCode;
    selectedRow.cells[2].innerHTML = formData.salary;
    selectedRow.cells[3].innerHTML = formData.city;
}

function onDelete(td) {
    if (confirm('Are you sure to delete this record ?')) {
        row = td.parentElement.parentElement;
        document.getElementById("employeeList").deleteRow(row.rowIndex);
        resetForm();
    }
}
function validate() {
    isValid = true;
    if (document.getElementById("fullName").value == "") {
        isValid = false;
        document.getElementById("fullNameValidationError").classList.remove("hide");
    } else {
        isValid = true;
        if (!document.getElementById("fullNameValidationError").classList.contains("hide"))
            document.getElementById("fullNameValidationError").classList.add("hide");
    }
    return isValid;
}
<table>
    <tr>
        <td>
          <form onsubmit="event.preventDefault();onFormsubmit();" autocomplete="off">
            <div>
            <label>Full Name</label>
            <input type="text" name="fullName">
            </div>
            <div>
               <label>Emp Code</label>
            <input type="text" name="empCode"> 
            </div>
            <div>
                <label>Salary</label>
            <input type="text" name="salary">
            </div>
            <div>
                <label>City</label>
            <input type="text" name="city">
            </div>
            <div class="form-action-buttons">
                <input type="submit" value="Submit">
            </div>
          </form>  
        </td>
        <td>
            <table class="list" id="employeeList">
                <thead>
                    <tr>
                        <th>Full Name</th>
                        <th>EMP Code</th>
                        <th>Salary</th>
                        <th>City</th>
                    </tr>
                </thead>
            </table>
        </td>
    </tr>
</table>

TypeScript: Type an Array of Generics with Dynamic Type Inference for Dependent Properties

I’m working on a form configuration system in TypeScript and I’m facing a type inference challenge. I need to define a type for an array of configuration objects, where each object has a query property that returns a promise of an array of a specific type. The key requirement is that other properties within the same configuration object (getOptionLabel and getOptionValue) must dynamically infer their parameter types based on the return type of that specific object’s query.

Here’s an example of the formConfig array I want to type-check:

const formConfig = [
    {
        name: 'category',
        label: 'Category',
        placeholder: 'select a category',
        query: async () => [{id: 1, categoryName: 'games'}, {id: 2, categoryName: 'movies'}],
        getOptionLabel: ({categoryName}) => categoryName,
        getOptionValue: ({id}) => id
    },
    {
        name: 'user',
        label: 'User',
        placeholder: 'select a user',
        query: async () => [{userId: 'u1', fullName: 'Alice Smith'}, {userId: 'u2', fullName: 'Bob Johnson'}],
        getOptionLabel: ({fullName}) => fullName, // 'fullName' should be inferred from user query
        getOptionValue: ({userId}) => userId
    }
];

The Challenge:

I want each element in the formConfig array to potentially handle a different data type returned by its query function.
For each individual object in the array, the getOptionLabel and getOptionValue callbacks must be strongly typed such that their input parameters (option) correctly reflect the element type T returned by that specific object’s query: () => Promise<T[]> (e.g., for ‘category’, option should be {id: number, categoryName: string}; for ‘user’, option should be {userId: string, fullName: string}).
TypeScript should ideally infer these types without me having to manually specify a generic type for each element or the array itself, maintaining full type safety when accessing properties within the callbacks.

If I define a simple generic interface:

interface FormConfigItem<T> {
    name: string;
    label: string;
    placeholder: string;
    query: () => Promise<T[]>;
    getOptionLabel: (option: T) => string;
    getOptionValue: (option: T) => string | number; // Assuming ID can be string or number
}

Then trying to use it in an array like const formConfig: FormConfigItem[] or FormConfigItem[] loses the specific type information for T within each element, leading to any or unknown for getOptionLabel and getOptionValue parameters, which defeats the purpose of strong typing. Creating a union like (FormConfigItem | FormConfigItem)[] also doesn’t work, as getOptionLabel would then expect CategoryType | UserType, not the specific type for that item.

How can I achieve this dynamic, per-item generic type inference and linkage in TypeScript?

Crud operation using html,css and javascript

I am performing crud operation using html,css and javascript. In this while i m running the web page it’s displaying the form structure but when i am giving the input its not taking or input is not getting saved. how i should resolve this and what mistake am i making there? why my data is not stored ,without storing data i can not perform the crud operation.

var selectedRow = null

function onFormSubmit() {
    if (validate()) {
        var formData = readFormData();
        if (selectedRow == null)
            insertNewRecord(formData);
        else
            updateRecord(formData);
        resetForm();
    }
}

function readFormData() {
    var formData = {};
    formData["fullName"] = document.getElementById("fullName").value;
    formData["empCode"] = document.getElementById("empCode").value;
    formData["salary"] = document.getElementById("salary").value;
    formData["city"] = document.getElementById("city").value;
    return formData;
}

function insertNewRecord(data) {
    var table = document.getElementById("employeeList").getElementsByTagName('tbody')[0];
    var newRow = table.insertRow(table.length);
    cell1 = newRow.insertCell(0);
    cell1.innerHTML = data.fullName;
    cell2 = newRow.insertCell(1);
    cell2.innerHTML = data.empCode;
    cell3 = newRow.insertCell(2);
    cell3.innerHTML = data.salary;
    cell4 = newRow.insertCell(3);
    cell4.innerHTML = data.city;
    cell4 = newRow.insertCell(4);
    cell4.innerHTML = `<a onClick="onEdit(this)">Edit</a>
                       <a onClick="onDelete(this)">Delete</a>`;
}

function resetForm() {
    document.getElementById("fullName").value = "";
    document.getElementById("empCode").value = "";
    document.getElementById("salary").value = "";
    document.getElementById("city").value = "";
    selectedRow = null;
}

function onEdit(td) {
    selectedRow = td.parentElement.parentElement;
    document.getElementById("fullName").value = selectedRow.cells[0].innerHTML;
    document.getElementById("empCode").value = selectedRow.cells[1].innerHTML;
    document.getElementById("salary").value = selectedRow.cells[2].innerHTML;
    document.getElementById("city").value = selectedRow.cells[3].innerHTML;
}
function updateRecord(formData) {
    selectedRow.cells[0].innerHTML = formData.fullName;
    selectedRow.cells[1].innerHTML = formData.empCode;
    selectedRow.cells[2].innerHTML = formData.salary;
    selectedRow.cells[3].innerHTML = formData.city;
}

function onDelete(td) {
    if (confirm('Are you sure to delete this record ?')) {
        row = td.parentElement.parentElement;
        document.getElementById("employeeList").deleteRow(row.rowIndex);
        resetForm();
    }
}
function validate() {
    isValid = true;
    if (document.getElementById("fullName").value == "") {
        isValid = false;
        document.getElementById("fullNameValidationError").classList.remove("hide");
    } else {
        isValid = true;
        if (!document.getElementById("fullNameValidationError").classList.contains("hide"))
            document.getElementById("fullNameValidationError").classList.add("hide");
    }
    return isValid;
}
<table>
    <tr>
        <td>
          <form onsubmit="event.preventDefault();onFormsubmit();" autocomplete="off">
            <div>
            <label>Full Name</label>
            <input type="text" name="fullName">
            </div>
            <div>
               <label>Emp Code</label>
            <input type="text" name="empCode"> 
            </div>
            <div>
                <label>Salary</label>
            <input type="text" name="salary">
            </div>
            <div>
                <label>City</label>
            <input type="text" name="city">
            </div>
            <div class="form-action-buttons">
                <input type="submit" value="Submit">
            </div>
          </form>  
        </td>
        <td>
            <table class="list" id="employeeList">
                <thead>
                    <tr>
                        <th>Full Name</th>
                        <th>EMP Code</th>
                        <th>Salary</th>
                        <th>City</th>
                    </tr>
                </thead>
            </table>
        </td>
    </tr>
</table>

Is there a way to know when a Google (GPT) ad is being closed?

So I have an ad stick to the bottom of the page. It has a closed icon, when i click on it, I need to understand if there is a way to know when an ad is closed?

I created this which let me know when when the ad i need is rendered:

'use client';

import { memo, useEffect } from 'react';

export interface StickyBannerState {
  height: number;
  present: boolean;
  slotID: string;
}

/**
 * dispatchUpdate
 *
 * @param detail - sticky banner state
 */
const dispatchUpdate = (detail: StickyBannerState): void => {
  window.dispatchEvent(
    new CustomEvent<StickyBannerState>('stickyBanner:update', { detail }),
  );
};

interface IAdStickyBridgeProps {
  slotID: string;
  enabled: boolean;
}

/**
 * AdStickyBridge
 *
 * Observes the ad slot element and emits sticky height changes.
 * Also listens for a "close" postMessage from the slot's iframe.
 *
 * Does not call GPT APIs. Safe alongside AdSlotClient.
 *
 * @param props - component props
 * @param props.slotID - ad slot element id
 * @param props.enabled - whether to enable observers
 */
function AdStickyBridge({
  enabled,
  slotID,
}: IAdStickyBridgeProps): React.ReactElement | null {
  useEffect(() => {
    if (!enabled || !slotID) {
      return;
    }

    let resizeObs: ResizeObserver | null = null;
    let mutationObs: MutationObserver | null = null;
    let lastHeight = -1;
    let lastPresent = false;

    /**
     * measureAndDispatch
     *
     * Measures the slot element and dispatches sticky state
     * only when values actually change.
     */
    const measureAndDispatch = (): void => {
      const el = document.getElementById(slotID);

      if (!el) {
        if (lastHeight !== 0 || lastPresent !== false) {
          lastHeight = 0;
          lastPresent = false;

          dispatchUpdate({ height: 0, present: false, slotID });
        }

        return;
      }

      const displayNone = Boolean(getComputedStyle(el)?.display === 'none');

      const h = displayNone ? 0 : Math.max(0, el.offsetHeight || 0);
      const present = h > 0;

      if (h !== lastHeight || present !== lastPresent) {
        lastHeight = h;
        lastPresent = present;

        dispatchUpdate({ height: present ? h : 0, present, slotID });
      }
    };

    /**
     * onMessage
     *
     * Handles postMessage coming from the slot iframe.
     * Expected payloads:
     * { type: 'ad-closed', slotId: '<slotID>' }
     * { event: 'ad-closed', slotId: '<slotID>' }
     *
     * @param ev - message event
     */
    const onMessage = (ev: MessageEvent): void => {
      // 1) Soft check payload shape
      const data = ev?.data as
        | { type?: string; event?: string; slotId?: string }
        | undefined;

      if (!data) {
        return;
      }

      console.log('marcelo data', data);

      const isClose = data.type === 'ad-closed' || data.event === 'ad-closed';

      if (!isClose) {
        return;
      }

      // 2) Scope to the correct slot:
      //     - If slotId is provided, require it to match.
      if (data.slotId && data.slotId !== slotID) {
        return;
      }

      // 3) Optional: verify the message comes from the slot's descendant iframe
      //    (prevents unrelated messages from other frames).
      const el = document.getElementById(slotID);
      if (!el) {
        return;
      }

      const frames = el.getElementsByTagName('iframe');
      let fromOurFrame = false;

      for (let i = 0; i < frames.length; i += 1) {
        if (frames?.[i]?.contentWindow === ev.source) {
          fromOurFrame = true;
          break;
        }
      }

      if (!fromOurFrame) {
        return;
      }

      // 4) Close instruction accepted → drop sticky offset
      dispatchUpdate({ height: 0, present: false, slotID });
    };

    // Initial measure after layout settles
    requestAnimationFrame(measureAndDispatch);

    // Resize observation
    const el = document.getElementById(slotID);
    if (el && 'ResizeObserver' in window) {
      resizeObs = new ResizeObserver(() => {
        measureAndDispatch();
      });
      resizeObs.observe(el);
    }

    // Watch the slot's parent (or body) for DOM/class/style changes
    const parent = el?.parentNode || document.body;

    mutationObs = new MutationObserver(() => {
      measureAndDispatch();
    });

    mutationObs.observe(parent, {
      attributeFilter: ['style', 'class'],
      attributes: true,
      childList: true,
      subtree: true,
    });

    window.addEventListener('message', onMessage);

    return (): void => {
      if (resizeObs) {
        resizeObs.disconnect();
      }

      if (mutationObs) {
        mutationObs.disconnect();
      }

      window.removeEventListener('message', onMessage);

      // Ensure wrapper returns to bottom on unmount
      dispatchUpdate({ height: 0, present: false, slotID });
    };
  }, [slotID, enabled]);

  return null;
}

export default memo(AdStickyBridge);

'use client';

import { memo, useEffect, useRef } from 'react';

import {
  defineSlot,
  getSlotById,
} from '@tu/utilities/helpers/ads/gpt/gptManager';
import type { IAdSettings } from '@tu/commons/ads/IAdSettings';
import useStore from '@tu/commons/store/Store';

import AdStickyBridge from './AdStickyBridge';

interface IAdSlotProps {
  adSettings: IAdSettings | null;
  lazyLoaded?: boolean;
}

/**
 * AdSlotClient
 *
 * @param props - component props
 * @param props.adSettings - ad settings
 * @param props.lazyLoaded - lazy loaded
 */
function AdSlotClient({
  adSettings,
  lazyLoaded,
}: IAdSlotProps): React.ReactElement | null {
  const hasLoad = useRef(false);
  const gptStarted = useStore((state) => !!state.scriptLoaded?.gptStarted);
  const hasOneTrust = useStore((state) => !!state.featureFlag?.hasOneTrust);

  useEffect(() => {
    let slot: googletag.Slot | undefined | null;

    if (!hasLoad.current && gptStarted && adSettings) {
      window.googletag = window.googletag || { cmd: [] };

      window.googletag.cmd.push(() => {
        if (!lazyLoaded) {
          const checkSlot = getSlotById(adSettings?.slotID);

          if (!checkSlot) {
            slot = defineSlot(adSettings, true, hasOneTrust);
          }
        }

        if (lazyLoaded) {
          slot = getSlotById(adSettings?.slotID);

          if (slot && document.getElementById(adSettings?.slotID)) {
            window.googletag.pubads().refresh([slot]);
          }
        }
      });

      hasLoad.current = true;
    }

    return (): void => {
      slot = null;
    };
  }, [adSettings, hasOneTrust, lazyLoaded, gptStarted]);

  if (!adSettings || lazyLoaded) {
    return null;
  }

  const isStickyCandidate =
    adSettings.position === 'ADH' ||
    adSettings.slotID.startsWith('div-gpt-ad-adh-');

  return (
    <>
      <div
        className="m-auto flex items-center text-center"
        id={adSettings.slotID}
      />
      <AdStickyBridge enabled={isStickyCandidate} slotID={adSettings.slotID} />
    </>
  );
}

export default memo(AdSlotClient);

But when I close it, nothing else comes back.
On another component I have this:

  const [stickyBanner, setStickyBanner] = useState<StickyBannerState>({
    height: 0,
    present: false,
    slotID: '',
  });

  useEffect(() => {
    /**
     * onUpdate
     *
     * @param ev - event
     */
    const onUpdate = (ev: Event): void => {
      const e = ev as CustomEvent<StickyBannerState>;

      console.log('marcelo e', e);

      if (!e.detail) {
        return;
      }

      setStickyBanner(e.detail);
    };

    window.addEventListener('stickyBanner:update', onUpdate as EventListener);

    return (): void =>
      window.removeEventListener(
        'stickyBanner:update',
        onUpdate as EventListener,
      );
  }, [nodeId]);

when the component mounts, stickyBanner.present and stickyBanner.height are falsy, after some second they become truthy and when i close the ad, nothing else changes back to falsy.

So is there a way to know when a Google (GPT) ad is being closed?

I want to reverse the direction of the slotreel, As of Now it is from bottom to top

I want to reverse the direction of the slotreel, As of Now it is from bottom to top.
but when I am reversing the direction it is creating gap on the top feels like stretching it,

Below is the code snippet , consider slotItem as just any text lets say but the problem is when I am reversing the direction it creates gap at the top, My aim to stop the movement of reel smoothly after 9-10 seconds when I found the result like it can be any of them , so from bottom to top it creates illusion but from top to bottom , it could not and as a result it shows gap at the top, so what could be done , any other better approach please !

import { FC, useEffect, useRef, useMemo, useCallback } from 'react';
import styles from './SpinningBarWheel.module.css';
import SlotItem from './spinBarHighlight/slotItem/SlotBackgroundItem';
import WheelHighlight from './spinBarHighlight/wheelHighlight/WheelHighlight';
// import { isMatchingPrize } from '../wheelDropModals/spinBarUtils';
import type { WinNotificationType, PrizedropPrizeType } from '@pp/core/src/api/fetchers/promotionsV2/types/promotions';

interface Props {
  spinBarItems: { text: string; color: string; isBaseColor?: boolean; prize?: PrizedropPrizeType }[];
  result: WinNotificationType;
}

const SpinningBarWheel: FC<Props> = ({ result, spinBarItems }) => {
  console.log(result, "result");
  
  const reelRef = useRef<HTMLDivElement>(null);
  const posRef = useRef(0);
  const animRef = useRef<number>();
  const winningIndexRef = useRef<number | null>(null);

  const rowHeight = 100;
  const reelLength = spinBarItems.length * rowHeight;

  const getMiddleOffset = () => window.innerHeight / 2 - rowHeight / 2;
  console.log(getMiddleOffset(), 'getMiddleOffset');
  

  // useEffect(() => {
  //   const handleResize = () => {
  //     if (winningIndexRef.current !== null && reelRef.current) {
  //       const loops = 10;
  //       const newOffset = getMiddleOffset();
  //       const targetPos = -((winningIndexRef.current + loops * spinBarItems.length) * rowHeight) + newOffset;

  //       posRef.current = targetPos;
  //       reelRef.current.style.transform = `translateY(${posRef.current % reelLength}px)`;
  //     }
  //   };

  //   window.addEventListener('resize', handleResize);
  //   return () => window.removeEventListener('resize', handleResize);
  // }, [spinBarItems.length, reelLength, rowHeight]);

  const getMiddleTextElement = useCallback(() => {
    if (!reelRef.current) return null;
    const rects = Array.from(reelRef.current.children) as HTMLDivElement[];
    const middleY = window.innerHeight / 2;
    for (const child of rects) {
      const rect = child.getBoundingClientRect();
      if (rect.top <= middleY && rect.bottom >= middleY) {
        return child.querySelector('span') as HTMLSpanElement;
      }
    }
    return null;
  }, []);

  const renderedSlotItems = useMemo(() => {
    const loops = 6;
    return Array.from({ length: Math.ceil(loops) }).flatMap((_, i) =>
      spinBarItems.map((item, j) => (
        <SlotItem
          key={`${i}-${j}`}
          text={item.text}
          color={item.color}
          isBaseColor={item.isBaseColor}
          // isFirst={i === 0 && j === 0} // Only true for the very first item
        />
      ))
    );
  }, [spinBarItems]);

  const easeOutCubic = useCallback((t: number) => 1 - Math.pow(1 - t, 3), []);

  useEffect(() => {
    const candidatePositions: number[] = [];

    spinBarItems.forEach((item, idx) => {
      if (idx === 3) {
        winningIndexRef.current = idx; // Save for snapping later
        console.log(idx, "idx");
        
        for (let loop = 0; loop < 20; loop++) {
          const pos = getMiddleOffset() - ((idx + loop * spinBarItems.length) * rowHeight);
          console.log(pos, "pos");
          
          candidatePositions.push(pos);
        }
      }
    });

    const target = candidatePositions[candidatePositions.length - 1];
    const start = posRef.current;
    const distance = target - start;
    const duration = 500;
    const startTime = Date.now();
    console.log({ target, start, distance }, 'animation start');
    

    const animate = () => {
      const elapsed = Date.now() - startTime;
      const t = Math.min(1, elapsed / duration);
      const eased = easeOutCubic(t);

      posRef.current = start + distance * eased;

      if (reelRef.current) {
        reelRef.current.style.transform = `translateY(${posRef.current % reelLength}px)`;
        console.log(posRef.current % reelLength, 'current pos');
        
      }

      if (t < 1) {
        animRef.current = requestAnimationFrame(animate);
      } else {
        const middleSpan = getMiddleTextElement();
        if (middleSpan) {
          middleSpan.classList.add(styles.resultScale);
          setTimeout(() => middleSpan.classList.remove(styles.resultScale), 4000);
        }
      }
    };

    animRef.current = requestAnimationFrame(animate);

    return () => {
      if (animRef.current) {
        cancelAnimationFrame(animRef.current);
      }
    };
  }, [result, spinBarItems, reelLength, easeOutCubic, getMiddleTextElement]);

  return (
    <>
      <div className={styles.speedlinesWrapper}>
        <div className={styles.speedlines}></div>
      </div>
      <div className={styles.speedlinesBlend}></div>
      <div className={styles.slotContainer}>
        <div ref={reelRef} className={styles.slotReel}>
          {renderedSlotItems}
        </div>
        <WheelHighlight />
      </div>
    </>
  );
};

export default SpinningBarWheel;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

Set up Prisma for cal.com

I am a beginner trying to contribute to open-source through cal.com (an open source calendly alternative). The thing is I am trying to setup Prisma on my system by using Yarn. I keep running into this issue.

I ran this syntax yarn add -D prisma@latest

I have installed postgreSQL on my system.

➤ YN0008: │ @prisma/engines@npm:5.22.0 must be rebuilt because its dependency tree changed
➤ YN0007: │ prisma@npm:6.16.1 [f9b2d] must be built because it never has been before or the last one failed
➤ YN0008: │ prisma@npm:6.8.2 [a80c8] must be rebuilt because its dependency tree changed
➤ YN0007: │ calcom-monorepo@workspace:. must be built because it never has been before or the last one failed
➤ YN0008: │ @prisma/client@npm:6.8.2 [a80c8] must be rebuilt because its dependency tree changed
➤ YN0009: │ calcom-monorepo@workspace:. couldn't be built successfully (exit code 1, logs can be found here: C:UsersPCAppDataLocalTempxfs-d1ac6272build.log)
➤ YN0000: └ Completed in 2m 25s
➤ YN0000: Failed with errors in 3m 1s
PS C:UsersPCDocumentsGsoccal.com> npx prisma generate --schema=./prisma/schema.prisma
warn The configuration property `package.json#prisma` is deprecated and will be removed in Prisma 7. Please migrate to a Prisma config file (e.g., `prisma.config.ts`).
For more information, see: https://pris.ly/prisma-config

Environment variables loaded from .env
Error: Could not load `--schema` from provided path `prismaschema.prisma`: file or directory not found

How to Render Webmaps using Zarr Format for Flood Data?

I have very large Geotiff Files (.tiff) for Flood Data –

$ gdalinfo flood_probability_2023-09-25_88.19823706960149_24.314907220056885.tif
Driver: GTiff/GeoTIFF
Files: flood_probability_2023-09-25_88.19823706960149_24.314907220056885.tif
       flood_probability_2023-09-25_88.19823706960149_24.314907220056885.tif.aux.xml
Size is 30530, 21403
Coordinate System is:
GEOGCRS["WGS 84",
    ENSEMBLE["World Geodetic System 1984 ensemble",
        MEMBER["World Geodetic System 1984 (Transit)"],
        MEMBER["World Geodetic System 1984 (G730)"],
        MEMBER["World Geodetic System 1984 (G873)"],
        MEMBER["World Geodetic System 1984 (G1150)"],
        MEMBER["World Geodetic System 1984 (G1674)"],
        MEMBER["World Geodetic System 1984 (G1762)"],
        MEMBER["World Geodetic System 1984 (G2139)"],
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]],
        ENSEMBLEACCURACY[2.0]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    USAGE[
        SCOPE["Horizontal component of 3D system."],
        AREA["World."],
        BBOX[-90,-180,90,180]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
Origin = (86.822531536265402,25.270686920623081)
Pixel Size = (0.000089831528412,-0.000089831528412)
Metadata:
  AREA_OR_POINT=Area
Image Structure Metadata:
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (  86.8225315,  25.2706869) ( 86d49'21.11"E, 25d16'14.47"N)
Lower Left  (  86.8225315,  23.3480227) ( 86d49'21.11"E, 23d20'52.88"N)
Upper Right (  89.5650881,  25.2706869) ( 89d33'54.32"E, 25d16'14.47"N)
Lower Right (  89.5650881,  23.3480227) ( 89d33'54.32"E, 23d20'52.88"N)
Center      (  88.1938098,  24.3093548) ( 88d11'37.72"E, 24d18'33.68"N)
Band 1 Block=30530x1 Type=Float64, ColorInterp=Gray
  Description = flood_label
  Min=0.000 Max=1.000
  NoData Value=nan
  Overviews: 15265x10702, 7633x5351, 3817x2676, 1909x1338, 955x669, 478x335, 239x168, 120x84, 60x42
  Metadata:
    STATISTICS_APPROXIMATE=YES
    STATISTICS_MAXIMUM=1
    STATISTICS_MEAN=0.0611193183464
    STATISTICS_MINIMUM=0
    STATISTICS_STDDEV=0.23954904982336
    STATISTICS_VALID_PERCENT=100
Band 2 Block=30530x1 Type=Float64, ColorInterp=Undefined
  Description = uncertainty
  Min=0.000 Max=0.333
  NoData Value=nan
  Overviews: 15265x10702, 7633x5351, 3817x2676, 1909x1338, 955x669, 478x335, 239x168, 120x84, 60x42
  Metadata:
    STATISTICS_APPROXIMATE=YES
    STATISTICS_MAXIMUM=0.33333333333333
    STATISTICS_MEAN=0.019859184446693
    STATISTICS_MINIMUM=0
    STATISTICS_STDDEV=0.058523799713129
    STATISTICS_VALID_PERCENT=100
Band 3 Block=30530x1 Type=Float64, ColorInterp=Undefined
  Description = flood_prob_1
  Min=0.000 Max=1.000
  NoData Value=nan
  Overviews: 15265x10702, 7633x5351, 3817x2676, 1909x1338, 955x669, 478x335, 239x168, 120x84, 60x42
  Metadata:
    STATISTICS_APPROXIMATE=YES
    STATISTICS_MAXIMUM=1
    STATISTICS_MEAN=0.10656160176136
    STATISTICS_MINIMUM=0
    STATISTICS_STDDEV=0.29088619554382
    STATISTICS_VALID_PERCENT=100
Band 4 Block=30530x1 Type=Float64, ColorInterp=Undefined
  Description = flood_prob_2
  Min=0.000 Max=1.000
  NoData Value=nan
  Overviews: 15265x10702, 7633x5351, 3817x2676, 1909x1338, 955x669, 478x335, 239x168, 120x84, 60x42
  Metadata:
    STATISTICS_APPROXIMATE=YES
    STATISTICS_MAXIMUM=1
    STATISTICS_MEAN=0.075278825662254
    STATISTICS_MINIMUM=0
    STATISTICS_STDDEV=0.25170630724278
    STATISTICS_VALID_PERCENT=100
Band 5 Block=30530x1 Type=Float64, ColorInterp=Undefined
  Description = flood_prob_3
  NoData Value=nan
  Overviews: 15265x10702, 7633x5351, 3817x2676, 1909x1338, 955x669, 478x335, 239x168, 120x84, 60x42

I want to make a web portal to visualize this file but since the data is very large, I’m converting it to Cloud Optimized Geotiff Format first using GDAL to convert it into 512X512 manageable block size.

$ gdal_translate input.tiff output.tiff -of COG -co COMPRESS=DEFLATE -co BIGTIFF=YES

By Doing so, I’m able to get a slightly compressed verion with internal blocking –

$ gdalinfo output_cog.tiff
Driver: GTiff/GeoTIFF
Files: output_cog.tiff
Size is 30530, 21403
Coordinate System is:
GEOGCRS["WGS 84",
    ENSEMBLE["World Geodetic System 1984 ensemble",
        MEMBER["World Geodetic System 1984 (Transit)"],
        MEMBER["World Geodetic System 1984 (G730)"],
        MEMBER["World Geodetic System 1984 (G873)"],
        MEMBER["World Geodetic System 1984 (G1150)"],
        MEMBER["World Geodetic System 1984 (G1674)"],
        MEMBER["World Geodetic System 1984 (G1762)"],
        MEMBER["World Geodetic System 1984 (G2139)"],
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]],
        ENSEMBLEACCURACY[2.0]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    USAGE[
        SCOPE["Horizontal component of 3D system."],
        AREA["World."],
        BBOX[-90,-180,90,180]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
Origin = (86.822531536265402,25.270686920623081)
Pixel Size = (0.000089831528412,-0.000089831528412)
Metadata:
  AREA_OR_POINT=Area
Image Structure Metadata:
  LAYOUT=COG
  COMPRESSION=LZW
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (  86.8225315,  25.2706869) ( 86d49'21.11"E, 25d16'14.47"N)
Lower Left  (  86.8225315,  23.3480227) ( 86d49'21.11"E, 23d20'52.88"N)
Upper Right (  89.5650881,  25.2706869) ( 89d33'54.32"E, 25d16'14.47"N)
Lower Right (  89.5650881,  23.3480227) ( 89d33'54.32"E, 23d20'52.88"N)
Center      (  88.1938098,  24.3093548) ( 88d11'37.72"E, 24d18'33.68"N)
Band 1 Block=512x512 Type=Float64, ColorInterp=Gray
  Description = flood_label
  NoData Value=nan
  Overviews: 15265x10701, 7632x5350, 3816x2675, 1908x1337, 954x668, 477x334
Band 2 Block=512x512 Type=Float64, ColorInterp=Undefined
  Description = uncertainty
  NoData Value=nan
  Overviews: 15265x10701, 7632x5350, 3816x2675, 1908x1337, 954x668, 477x334
Band 3 Block=512x512 Type=Float64, ColorInterp=Undefined
  Description = flood_prob_1
  NoData Value=nan
  Overviews: 15265x10701, 7632x5350, 3816x2675, 1908x1337, 954x668, 477x334
Band 4 Block=512x512 Type=Float64, ColorInterp=Undefined
  Description = flood_prob_2
  NoData Value=nan
  Overviews: 15265x10701, 7632x5350, 3816x2675, 1908x1337, 954x668, 477x334
Band 5 Block=512x512 Type=Float64, ColorInterp=Undefined
  Description = flood_prob_3
  NoData Value=nan
  Overviews: 15265x10701, 7632x5350, 3816x2675, 1908x1337, 954x668, 477x334

I am then converting this COG file to Zarr Store using rasterio

LEVELS = 6  
store_2d = "./output.zarr"
path = "./input.tiff"

# open dataset
ds = (
    xr.open_dataarray(path, engine="rasterio")
    .to_dataset(name="tavg")
    .squeeze()
)

# create the pyramid
dt = pyramid_reproject(ds, levels=LEVELS, clear_attrs=True)

# write to zarr
dt.to_zarr(store_2d, zarr_format=2, consolidated=True)

This is the information of this newly created Zarr folder –

C:UsersBatmanDesktopTechBTPNPyramidTryWithCarbonMaps>gdalinfo C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr
Driver: Zarr/Zarr
Files: C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr
Size is 512, 512
Subdatasets:
  SUBDATASET_1_NAME=ZARR:"C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr":/0/tavg
  SUBDATASET_1_DESC=[5x128x128] /0/tavg (Float32)
  SUBDATASET_2_NAME=ZARR:"C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr":/1/tavg
  SUBDATASET_2_DESC=[5x256x256] /1/tavg (Float32)
  SUBDATASET_3_NAME=ZARR:"C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr":/2/tavg
  SUBDATASET_3_DESC=[5x512x512] /2/tavg (Float32)
  SUBDATASET_4_NAME=ZARR:"C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr":/3/tavg
  SUBDATASET_4_DESC=[5x1024x1024] /3/tavg (Float32)
  SUBDATASET_5_NAME=ZARR:"C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr":/4/tavg
  SUBDATASET_5_DESC=[5x2048x2048] /4/tavg (Float32)
  SUBDATASET_6_NAME=ZARR:"C:/Users/Batman/Desktop/Tech/BTP/Data/flood_pyramid.zarr":/5/tavg
  SUBDATASET_6_DESC=[5x4096x4096] /5/tavg (Float32)
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,  512.0)
Upper Right (  512.0,    0.0)
Lower Right (  512.0,  512.0)
Center      (  256.0,  256.0)

I want to make a web portal to let the client visualize this, I want to serve this dynamically in a tiled way so that depending on the user’s zoom level, data is requested from the server.

I have looked up everything including @carbonmaps, zarrita, zarr-js, but I am unable to do this.
There is no restrictions for Javascript on Frontend, any system works.

This is the code, I am using in @carbonmaps –

'use client';

import { useEffect, useRef } from 'react';
import { Map, Tile, useColormap } from '@carbonplan/maps';

// Simple theme object (mimics CarbonPlan's dark background)
const theme = {
  colors: {
    background: '#1a1a1a', // or '#000'
  },
};

const ZarrMapPage = () => {
  const canvasRef = useRef();

  // Define colormap
  const colormap = useColormap({
    name: 'fire',     // Try 'warm', 'viridis', 'blues', etc.
    flip: false,
    clamp: null,      // Set [min, max] if needed, or leave null
  });

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    // Handle HiDPI rendering
    const resize = () => {
      const { offsetWidth, offsetHeight } = canvas;
      canvas.width = offsetWidth * devicePixelRatio;
      canvas.height = offsetHeight * devicePixelRatio;
      canvas.style.width = `${offsetWidth}px`;
      canvas.style.height = `${offsetHeight}px`;
    };
    resize();
    window.addEventListener('resize', resize);

    const gl = canvas.getContext('webgl2');
    if (!gl) {
      console.error('WebGL2 is not supported');
      return;
    }

    // Create Tile layer
    const tile = new Tile({
      gl,
      source: '/data/mydata.zarr',     // Adjust path to your .zarr
      variable: 'temperature',         // Change to your Zarr variable
      colormap: colormap.get(),
      clim: [250, 310],                // Adjust based on your data
      transform: 'identity',
      projection: 'equal-earth',       // Or 'albers-usa', 'mercator'
      onLoadingStatus: (status) => console.log(status),
    });

    // Animation loop
    const loop = () => {
      tile.draw();
      requestAnimationFrame(loop);
    };
    loop();

    // Cleanup
    return () => {
      tile.destroy();
      window.removeEventListener('resize', resize);
    };
  }, [colormap]);

  return (
    <div
      style={{
        width: '100vw',
        height: '100vh',
        position: 'relative',
        background: theme.colors.background,
      }}
    >
      <Map
        settings={{
          projection: 'equal-earth',
          zoom: 1,
          center: [0, 0],
        }}
      >
        <canvas
          ref={canvasRef}
          style={{
            display: 'block',
            width: '100%',
            height: '100%',
            background: theme.colors.background,
          }}
        />
      </Map>
    </div>
  );
};

export default ZarrMapPage;   

But I got this error –

mport trace for requested module:
./app/page.js
 ⨯ TypeError: (0 , _carbonplan_maps__WEBPACK_IMPORTED_MODULE_2__.useColormap) is not a function
    at ZarrMapPage (apppage.js:17:31)
  15 |
  16 |   // Define colormap
> 17 |   const colormap = useColormap({
     |                               ^
  18 |     name: 'fire',     // Try 'warm', 'viridis', 'blues', etc.
  19 |     flip: false,
  20 |     clamp: null,      // Set [min, max] if needed, or leave null {
  digest: '3505414644'

I would like your help in this.

How to optimize lazy loading of images in a blog built with Next.js?

I’m working on a personal project mygamediarys, which is a blog where I share gaming diaries. The site is built using Next.js and hosted on Vercel.

The problem is that when I load long posts with many screenshots, the initial page load feels slow. I tried using Next.js component with loading=”lazy”, but it doesn’t seem to work consistently on mobile browsers.

What’s the best way to implement image lazy loading in Next.js to improve performance on a blog like this? Should I use a third-party library such as react-lazyload, or rely on native browser support?

Added next-optimized-images plugin (but it conflicts with Next.js 13).

Used priority={false} but no visible difference.

Any recommendations for a production-ready setup?

Js Saving Students bio issues [closed]

I have single one coding, please HTML, CSS all are normal and fine to my view, while on Js I have 1 Minor issue, if I save students bio go-to admin dashboard like I expect, also when students bio save let it in two dashboard like I wrote in my coding, but only data go-to admin dashboard but not stay too in teacher dashboard students table of summary

I tried to find the issues I can’t

How can I create a Control Page for my Esp32 devices?

I am working on a small IoT personal project with some esp32 powered devices. The devices are controlled with a web interface, and all have the same program inside, basically a multifunction timer with sensors and relays. Interface is driven by Esp32AsyncWebserver. I have a “let’s look it up in StackOverflow” programming knowledge and I was able to get them running and working fine. I also designed the PCB and got it manufactured for cheap in China, and that is WAY more that I expexted I was able to do!

Now the problem: I would like to setup a “Controlling interface” where all the devices are showing up, as many IoT apps do (see: Google >Home, TP-Link Tapo etc), and I’m not able to conjure up something working. This is what I tried so far:

  • first approach eas to give each device an unique, hardcoded, fixed IP then creating a static HTML linking to each device. I would like to avoid this as I would need to program each device one by one, make a list of the devices-IPs, reserve the IPs in the router so that they are not assigned to other stuff in the network. This would also prevent me to bring them with me and hook them up into someone’s else wifi (they have an inbuilt wifi manager so moving them around would not be a problem “per se”)
  • I then tried an HTML page with a JavaScript function to scan my network. First approach was to give all the devices a specific Hostname and look for it, but apparently JS is not able to read Local Network Hostnames, or at least I couldn’t find how. I then tried adding a “ping_me” page in each device and ask JS to scan my network for any active “http:192.168.1.xping_me” page, and that kind of worked, only problem is that the fetch() function in JS takes ages to give up a non existing IPs. It took nearly 5 minutes to run through a 10 IP test range
  • As a last, desperate attempt I also gave a try to AI app generators. Browser based ones told me that “browser cannot do what I ask due to browser limitations”. Native android app generators did’t work at all (wouldn’t say :D)
  • I’ve seen the Arduino IoT library but I’d rather to keep things “local” and not “cloud”

Given my absolute lack of knowledge in Android app creation, I still think that the HTML+JS approach is the best approach. Is there any way to have a fast network scan in JS, something like “check if IP is used and look for the ping_me page only for existing >IPs”? I’m also open to suggestions for other approaches to the problem.
Thanks in advance to anyone who will try help! 🙂

Can someone explain me please , why am I getting different results [closed]

I was trying to search the index of a substring “id” in the string = “Widget with id”which is at 12th position. But I am getting wrong result as ‘1’. Why ? enter image description here

I was trying to search the index of substring using .indexOf but I was getting different results for str1. I am getting 1 as a result, when I was supposed to get 12 while searching it using the .index of().
Although it’s giving me the correct index for other string I tried to search.
When I am adding the position value to it it’s giving me the right result as 12. enter image description here

Getting Code Not Found Error in Vercel Deploynment for Node JS Application

I’m trying to deploy my Node.js backend on Vercel, and after the deployment, which showed no error in the build process, and was deployed. I’m seeing 404 Error, Code Not Found.
I have added the vercel.json file as stated in other similar answers, but none of them are backend-specific, and my problem is not solved. I’m still seeing the error.

I’m using TypeScript and a Turborepo mono-repo for this project.

Here is the code to reproduce my problems:

//tsconfig.json
{
  "compilerOptions": {
    "module": "nodenext",
    "target": "esnext",
    "types": [],
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "strict": true,
    "jsx": "react-jsx",
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "skipLibCheck": true,
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
//package.json

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "dist/Server.js",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "dev": "tsx watch src/Server.ts",
    "start": "node dist/Server.js",
    "check-types": "tsc --noEmit",
    "lint": "eslint ."
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mongoose": "^8.18.0"
  },
  "devDependencies": {
    "tsx": "^4.20.5"
  }
}
//app>src>Server.ts
import express from "express";

if (process.env.NODE_ENV !== "production") {
  import("dotenv").then((dotenv) => dotenv.config({ path: "./.env" }));
}
const app: express.Application = express();
app.use(express.json());

app.get("/", (req, res) => {
  res.send("Hello From the server");
});

app.get("/api/v1/health", (req, res) => {
  res.json({ status: "OK" });
});


if (process.env.VERCEL === undefined) {
  app.listen(process.env.PORT || 3000, () => {
    console.log(`The app is running on PORT: ${process.env.PORT || 3000}`);
  });
}

export default app;

I want to know why this is happening for node js specific application and how to resolve this issue.

Thanks in advance

Hi I want to add option product prices into the main product price which is shown above the 2 option product prices in the image

enter image description here
I want to add the option product prices into to the main product price shown above the 2 options , when quantities of either of one increase will reflect or add in the main product price shown above.
I am attaching another images for reference.

[option prices added in the main product price when quantities increase of the option product either of any real time .](https://i.sstatic.net/fkuPsE6t.jpg)